[BZOJ1103][POI2007]大都市meg(dfs序+bit||链剖)
2016-10-13 21:37
405 查看
题目描述
传送门题解
链剖裸题对不对吖~然而ATP大爷觉得写模板题太low了,于是教我写bit。
用dfs序将一个点拆成两个点,在in点加正权,out点加负权,这样查询一个点到根路径上的权就是差这个点in的前缀和。辣样的话用一个bit维护就可以了。
代码
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define N 250005 int n,m,a,b,dfs_clock,ans; int tot,point ,nxt[N*2],v[N*2]; int C[N*2],in[N*2],out[N*2]; void addedge(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; } void add(int loc,int val) { for (int i=loc;i<=2*n;i+=i&(-i)) C[i]+=val; } int query(int loc) { int ans=0; for (int i=loc;i>=1;i-=i&(-i)) ans+=C[i]; return ans; } void dfs(int x,int fa) { in[x]=++dfs_clock; if (x!=1) add(dfs_clock,1); for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x); out[x]=++dfs_clock; if (x!=1) add(dfs_clock,-1); } int main() { scanf("%d",&n); for (int i=2;i<=n;++i) { scanf("%d%d",&a,&b); addedge(a,b); } dfs(1,0); scanf("%d",&m); for (int i=1;i<=n+m-1;++i) { char opt=getchar(); while (opt!='A'&&opt!='W') opt=getchar(); if (opt=='A') { scanf("%d%d",&a,&b); if (in[a]<in[b]) swap(a,b); add(in[a],-1); add(out[a],1); } else { scanf("%d",&a); ans=query(in[a]); printf("%d\n",ans); } } }
总结
①这个dfs序+bit的思路非常有用!感谢ATP神犇!相关文章推荐
- [BZOJ]1103: [POI2007]大都市meg
- BZOJ1103: [POI2007]大都市meg
- BZOJ 1103: [POI2007]大都市meg
- BZOJ 1103: [POI2007]大都市meg(dfs序,树状数组)
- 8.3 bzoj1103 [POI2007]大都市meg
- bzoj1103 POI2007 大都市meg
- [bzoj1103][poi2007]大都市meg(DFS序)
- 【POI2007】【Bzoj 1103】大都市meg
- bzoj1103 [POI2007]大都市meg
- 【DFS序+线段树】BZOJ1103 [POI2007]大都市meg
- bzoj1103 [POI2007]大都市meg(树+差分+树状数组)
- 【BZOJ 1103】 [POI2007]大都市meg
- BZOJ 1103: [POI2007]大都市meg
- BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)
- 【BZOJ1103】[POI2007]大都市meg
- 【bzoj1103】【POI2007】【大都市】【meg】【人工栈】
- BZOJ 1103: [POI2007]大都市meg( 树链剖分 )
- 【BZOJ】【1103】【POI2007】大都市meg
- bzoj1103: [POI2007]大都市meg
- [POI2007][BZOJ1103] 大都市meg|dfs序|树状数组