传送门:嘟嘟嘟

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

想一下,如果我们改一条边,那么影响的只有他的子树,只要先搞一个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. winform窗体 小程序【三级联动】

    三级联动[省,市,区] 类似地区选择,当选的某个省份,后面的下拉框相对变成对应省份的区县 实现省市区联动关键是数据库的表,[每个省内区的AreaCode列是同样的] public Form2() { ...

  2. 无法将类型“System.Collections.Generic.List<anonymous type:string ClassID,string ClsssName>”隐式转换为“System.Collections.Generic.List<Ecology.Model.EnergyFlowGraph>”

    无法将类型“System.Collections.Generic.List<anonymous type:string ClassID,string ClsssName>”隐式转换为“Sy ...

  3. 记一次webapi传参数的问题

    .net小白一枚,经过了几个小时的研究,由于错误的写法导致后台始终接受不到前台传递过来的参数.首先看看控制器的参数 public Core.MVC.ServiceResult<DTO.Out.M ...

  4. Gold Rush(hnu13249)

    Gold Rush Time Limit: 2000ms, Special Time Limit:5000ms, Memory Limit:65536KB Total submit users: 15 ...

  5. 卸载阿里云自带svn

  6. 5月7日——采用第三方页面内容,但是顶部title使用自己的

          --------->       由A页面进入我的页面 代码如下: (1)A页面下需要添加的代码 (2)我的页面下需要添加的代码 此处用到的语法为mui框架中的语法,可参照mui官方 ...

  7. Hibernate 中配置属性详解(hibernate.properties)

    Hibernate能在各种不同环境下工作而设计的, 因此存在着大量的配置参数.多数配置参数都 有比较直观的默认值, 并有随 Hibernate一同分发的配置样例hibernate.properties ...

  8. 在线报表设计实战系列 – 制作多Y轴组合图表(8)

    葡萄城报表是一套强大的报表开发和系统搭建工具,既能与您开发的报表软件项目紧密集成,也可独立部署运行,支持多数据源,具有无编码.灵活.稳定等特性,可以帮您快速搭建专业的报表软件系统,实现各类报表的设计. ...

  9. terminate called after throwing an instance of 'std::bad_alloc'

    这个错误,网上搜索到的资料大多是指向内存不足或者内存碎片问题,如下链接 http://bbs.csdn.net/topics/330000462 http://stackoverflow.com/qu ...

  10. js判断数组是否包含某个字符串变量

    最近碰到一个这样的现象,后台返回的数据中,数组里面有一些有变量值,有一些没有变量值. 举个例子,比如后台返回的例子是这样的: var arr=[ { "status":" ...