首页 > 代码库 > 【BZOJ】1103: [POI2007]大都市meg
【BZOJ】1103: [POI2007]大都市meg
http://www.lydsy.com/JudgeOnline/problem.php?id=1103
题意:一棵n节点的树(1<=n<=250000),m条边(1<=m<=250000-1),权值为1,有n+m-1个操作:操作W u:询问u到根的权值和; 操作A u v,将边(u, v)的权值减去1
#include <bits/stdc++.h>using namespace std;const int N=250005;int n, ihead[N], cnt;struct dat { int next, to; }e[N<<1];void add(int u, int v) { e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u;}int dep[N], tot, FF[N], LL[N];void dfs(int x, int fa) { FF[x]=++tot; for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=fa) dep[e[i].to]=dep[x]+1, dfs(e[i].to, x); LL[x]=tot;}int c[N];void upd(int x, int s) { for(; x<=n; x+=x&-x) c[x]+=s; }int sum(int x) { int ret=0; for(; x; x-=x&-x) ret+=c[x]; return ret; }int main() { scanf("%d", &n); for(int i=0; i<n-1; ++i) { int u, v; scanf("%d%d", &u, &v); add(u, v); } dfs(1, 0); int m; scanf("%d", &m); for(int k=0; k<m+n-1; ++k) { int u, v; char s[2]; scanf("%s%d", s, &u); if(s[0]==‘W‘) { printf("%d\n", sum(FF[u])+dep[u]); } else { scanf("%d", &v); if(dep[u]<dep[v]) swap(u, v); upd(FF[u], -1); upd(LL[u]+1, 1); } } return 0;}
做过dfs序的应该都会吧...
很显然,每次更改一条边,影响了深度大一点的节点的所有子树,询问就是询问1-当前点的权值和就行了
所以我们维护一下dfs序和前缀和即可
【BZOJ】1103: [POI2007]大都市meg
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。