传送门:嘟嘟嘟

第一反应是树链剖分,但是太长懒得写,然后就想出了一个很不错的做法。

想一下,如果我们改一条边,那么影响的只有他的子树,只要先搞一个dfs序,为什么搞出这个呢?因为有一个性质:一个节点的子树在dfs序上是连续的,所以这道题就变成了一个单点查询,区间修改的线段树(树状数组)板子题。

然后我不到40分钟写完了,非说有的点TLE,debug了一个多点……现在想想,一般遇到这种情况,一定不是什么正经问题。然而当时的我并不这么想,以为线段树太慢了,改成差分+树状数组,各种优化,虽然在luogu卡了过去,然而内网却GG。

终于放弃,到网上找标程,发现写的几乎一模一样,就一行行比对……然后发现我为了省事儿读字母用了cin,按标称改成了scanf……结果最慢的点直接从900多ms变成了200多ms……然后内网秒过了……老子在此立flag:我,mrclr,如果再用cin,我就女装!

心路历程讲完了,发下代码吧

先是线段树的

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdlib>
#include<cctype>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 3e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n;
vector<int> v[maxn]; int dis[maxn], dfsx[maxn], size[maxn], pos[maxn], cnt = ;
void dfs(const int& now)
{
dfsx[now] = ++cnt; pos[cnt] = now;
size[now] = ;
for(int i = ; i < (int)v[now].size(); ++i)
{
dis[v[now][i]] = dis[now] + ;
dfs(v[now][i]);
size[now] += size[v[now][i]];
}
return;
} int l[maxn << ], r[maxn << ], dis2[maxn << ], lazy[maxn << ];
void build(const int& L, const int& R, const int& now)
{
l[now] = L; r[now] = R;
if(L == R) {dis2[now] = dis[pos[L]]; return;}
int mid = (L + R) >> ;
build(L, mid, now << );
build(mid + , R, now << | );
dis2[now] = dis2[now << ] + dis2[now << | ];
}
void pushdown(const int& now)
{
if(lazy[now])
{
lazy[now << ] += lazy[now];
lazy[now << | ] += lazy[now];
dis2[now << ] -= lazy[now];
dis2[now << | ] -= lazy[now];
lazy[now] = ;
}
}
void update(const int& L, const int& R, const int& now)
{
if(!dis2[now]) return;
if(l[now] == L && r[now] == R)
{
dis2[now]--; lazy[now]++;
return;
}
pushdown(now);
int mid = (l[now] + r[now]) >> ;
if(R <= mid) update(L, R, now << );
else if(L > mid) update(L, R, now << | );
else {update(L, mid, now << ); update(mid + , R, now << | );}
}
int query(const int& id, const int& now)
{
if(!dis2[now]) return ;
if(l[now] == r[now]) return dis2[now];
pushdown(now);
int mid = (l[now] + r[now]) >> ;
if(id <= mid) return query(id, now << );
else return query(id, now << | );
} int main()
{
n = read();
for(int i = ; i < n; ++i)
{
int x = read(), y = read();
if(y < x) swap(x, y);
v[x].push_back(y);
}
dfs();
build(, cnt, );
int m = read();
char ch[];
for(int i = ; i < n + m; ++i)
{
scanf("%s", ch);
if(ch[] == 'W')
{
int x = read();
write(query(dfsx[x], )); enter;
}
else
{
int x = read(), y = read();
if(y > x) swap(x, y);
update(dfsx[x], dfsx[x] + size[x] - , );
}
}
return ;
}

然后又写了个差分+树状数组

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdlib>
#include<cctype>
using namespace std;
#define enter printf("\n")
#define space putchar(' ')
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 3e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
} int n;
vector<int> v[maxn]; int dis[maxn], dfsx[maxn], size[maxn], pos[maxn], cnt = ;
void dfs(const int& now)
{
dfsx[now] = ++cnt; pos[cnt] = now;
size[now] = ;
if(!v[now].size()) return;
for(int i = ; i < (int)v[now].size(); ++i)
{
dis[v[now][i]] = dis[now] + ;
dfs(v[now][i]);
size[now] += size[v[now][i]];
}
} int cf[maxn], c[maxn];
inline int lowbit(int x)
{
return x & -x;
}
void add(int pos, int x)
{
while(pos <= cnt)
{
c[pos] += x;
pos += lowbit(pos);
}
}
int sum(int pos)
{
int ret = ;
while(pos)
{
ret += c[pos];
pos -= lowbit(pos);
}
return ret;
} int main()
{
n = read();
for(int i = ; i < n; ++i)
{
int x = read(), y = read();
if(y < x) swap(x, y);
v[x].push_back(y);
}
dfs();
for(int i = ; i <= cnt; ++i) cf[i] = dis[pos[i]] - dis[pos[i - ]];
for(int i = ; i <= cnt; ++i) add(i, cf[i]);
int m = read();
char ch[];
for(int i = ; i < n + m; ++i)
{
scanf("%s", ch);
if(ch[] == 'W')
{
int x = read();
write(sum(dfsx[x])); enter;
}
else
{
int x = read(), y = read();
if(y > x) swap(x, y);
add(dfsx[x], -); add(dfsx[x] + size[x], );
}
}
return ;
}

虽然都能过,不过树状数组比线段树快了一倍

[POI2007]MEG-Megalopolis的更多相关文章

  1. NOIp2018 复习笔记

    其实也没什么用啦,只是来占个坑 OI知识 3367 [模板]并查集 就这么做啊 没什么其他的 就是可以做tarjan LCA和Kruskal的操作 //关键函数 int getfa(int t) { ...

  2. BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2221  Solved: 1179[Submit][Sta ...

  3. BZOJ 1103: [POI2007]大都市meg

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2189  Solved: 1160[Submit][Sta ...

  4. [bzoj1103][POI2007]大都市meg(树状数组+dfs序)

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2031  Solved: 1069[Submit][Sta ...

  5. 【BZOJ】【1103】【POI2007】大都市meg

    dfs序 模板题,进点+1出点-1,刚好对于不在路径上的点一进一出刚好抵消,由于本题要动态修改(变成公路以后+1-1都变成0)所以在序列上套一个树状数组即可. TLE:1.递归dfs给爆了……写了个手 ...

  6. 数据结构(线段树):BZOJ 1103 [POI2007]大都市meg

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1791  Solved: 925[Submit][Stat ...

  7. BZOJ 1103: [POI2007]大都市meg( 树链剖分 )

    早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了.. 树链剖分 , 为什么跑得这么慢... ------------------------------------------- ...

  8. bzoj1103【POI2007】大都市meg

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1544  Solved: 776 [Submit][St ...

  9. BZOJ1103 [POI2007]大都市meg 【树剖】

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3038  Solved: 1593 [Submit][S ...

  10. 树状数组【bzoj1103】: [POI2007]大都市meg

    1103: [POI2007]大都市meg 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡 ...

随机推荐

  1. eclipse连接VisualSVN Server

    1.下载安装VisualSVN Server 2.修改资源库的网络连接.去掉默认的选中,修改端口,点击ok. 3.新建资源库Test,显示连接的地址http://svnybb/svn/Test/ .之 ...

  2. MyBatis动态添加—trim标签

    做添加时,部分字段有值,没值的字段不添加,这就是动态添加,使用 trim 标签就可以实现. <insert id="insertSysUser" parameterType= ...

  3. 如何调试JDK源代码并查看局部变量值

    如下图: 按F5进入String.startsWith,如下: 点“Edit Source Lookup Path” 附加源代码,如下图: 附加上源代码后如下: 可以看到,当鼠标放在“prefix”上 ...

  4. Java JDBC MySQL

    一.驱动 下载地址:https://dev.mysql.com/downloads/connector/j/ 二.数据库连接配置 jdbc:mysql://address:port/database? ...

  5. java.lang.ExceptionInInitializerError异常

    今天在开发的过程中,遇到java.lang.ExceptionInInitializerError异常,百度查了一下,顺便学习学习,做个笔记 静态初始化程序中发生意外异常的信号,抛出Exception ...

  6. CentOS 7环境下Pycharm安装流程记录

    1.准备安装文件: 方法1: 使用内置火狐浏览器访问下载最新格式为tar.gz的压缩包 网址:https://www.jetbrains.com/pycharm/download/previous.h ...

  7. webpack打包小图片时进行Base64转码

    关于base64 优点: base64就是一串字符串码表示的图片,在加载页面和js时一块加载出来,减少了加载图片时的http请求.加载一张图片时会发起一次http请求,http请求每次建立都会需要一定 ...

  8. BZOJ2388: 旅行规划(分块 凸包)

    题意 题目链接 Sol 直接挂队爷的题解了 分块题好难调啊qwq #include<bits/stdc++.h> #define LL long long using namespace ...

  9. AndroidGradle最实用的指南

    AndroidStudio目前已经成为Android开发人员的主流工具,而Gradle的原理,配置,使用仍然是很多android开发人员感到困惑的地方.网上虽然有很多相关文档,但是要么是只会用但是不知 ...

  10. CSS 小结笔记之BFC

    BFC 即为Block formatting context 的缩写,BFC 主要用来将一个盒子设置为一个隔离的容器,不管盒子内部的元素具有什么属性,都不会影响到盒子的外面. 1.哪些元素能产生BFC ...