【手动开栈】【dfs序】【树状数组】【Tarjan】bzoj2819 Nim
2015-03-09 21:26
387 查看
考虑树状数组区间修改(只对其子树的答案有影响)点查询,每个点记录的是它到根路径上的权值异或和。
答案时query(L)^query(R)^a[lca]。
这种方法在支持区间加法、减法的树上询问的时候可以避免树链剖分。
可能爆栈,考虑手动开栈。(诶诶Tarjan预处理lca的时候怎么没手动开栈?不要在意^_^)
实际上不会爆的。
答案时query(L)^query(R)^a[lca]。
这种方法在支持区间加法、减法的树上询问的时候可以避免树链剖分。
可能爆栈,考虑手动开栈。(诶诶Tarjan预处理lca的时候怎么没手动开栈?不要在意^_^)
实际上不会爆的。
#include<cstdio> #include<stack> #include<algorithm> #include<queue> #include<cmath> #include<vector> using namespace std; #define N 500001 typedef pair<int,int> Point; vector<Point>ask ; int n,a ,b ,m,ancestor ; int en,first ,next[N<<1],v[N<<1]; int FA ,rank ,lcas ; void AddEdge(const int &U,const int &V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int findroot(int x){return FA[x]==x?x:findroot(FA[x]);} void Union(int x,int y) { int U=findroot(x); int V=findroot(y); if(rank[U]<rank[V]) FA[U]=V; else { FA[V]=U; if(rank[U]==rank[V]) ++rank[U]; } } bool vis ; void LCA(int U,int Fa) { ancestor[U]=U; for(int i=first[U];i;i=next[i]) if(v[i]!=Fa) { LCA(v[i],U); Union(U,v[i]); ancestor[findroot(U)]=U; } vis[U]=1; for(int i=0;i<ask[U].size();i++) if(vis[ask[U][i].first]) lcas[ask[U][i].second]=ancestor[findroot(ask[U][i].first)]; } stack<int>st; queue<int>q; int tot,Ls ,Rs ,root=1; void dfs() { st.push(1); Ls[1]=++tot; b[1]=a[1]; while(!st.empty()) { int U=st.top(); bool flag=0; for(int i=first[U];i;i=next[i]) if(!Ls[v[i]]) { Ls[v[i]]=++tot; b[v[i]]=(a[v[i]]^b[U]); st.push(v[i]); first[U]=next[i]; flag=1; break; } if(!flag) { Rs[U]=tot; st.pop(); } } } int d ; void add_node(int p,const int &v){for(;p<=n;p+=(p&(-p)))d[p]^=v;} void add_range(const int &L,const int &R,const int &v){add_node(L,v);if(R!=n)add_node(R+1,v);} int query(int p){int res=0;for(;p;p-=(p&(-p)))res^=d[p];return res;} int A ,B ; char op [2]; int main() { int x,y; scanf("%d",&n); for(int i=1;i<=n;++i) { FA[i]=i; scanf("%d",&a[i]); } for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } scanf("%d",&m); for(int i=1;i<=m;++i) { scanf("%s%d%d",op[i],&A[i],&B[i]); if(op[i][0]=='Q') { ask[A[i]].push_back(make_pair(B[i],i)); ask[B[i]].push_back(make_pair(A[i],i)); } } LCA(1,0); dfs(); for(int i=1;i<=n;++i) add_range(Ls[i],Ls[i],b[i]); for(int i=1;i<=m;++i) if(op[i][0]=='Q') puts((query(Ls[A[i]])^query(Ls[B[i]])^a[lcas[i]])?"Yes":"No"); else { add_range(Ls[A[i]],Rs[A[i]],a[A[i]]^B[i]); a[A[i]]=B[i]; } return 0; }
相关文章推荐
- [BZOJ2819]Nim-树状数组-dfs序
- [BZOJ2819] Nim && dfs序 + 树状数组 + LCA
- BZOJ 2819: Nim dfs序维护树状数组,倍增
- BZOJ 2819: Nim( nim + DFS序 + 树状数组 + LCA )
- bzoj 2434 (NOI2011)阿狸的打字机 【AC自动机】【树状数组】【DFS序】
- BZOJ 2434 阿狸的打字机 补全AC自动机 ( Trie图 ) fail树 树状数组 DFS序列
- [dfs序 树状数组] BZOJ 4034 [HAOI2015]T2
- 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
- bzoj 4756: [Usaco2017 Jan]Promotion Counting【dfs+树状数组】
- [LCA][dfs序]BZOJ 2819: Nim
- [BZOJ 2819]NIM(dfs序维护树上xor值)
- BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]
- BZOJ2819 Nim(DFS序)
- bzoj2434 [Noi2011]阿狸的打字机 ( AC自动机 & fail树 + 树状数组 + dfs序 )
- BZOJ 1103 [POI 2007] dfs序+树状数组 解题报告
- bzoj 4448: [Scoi2015]情报传递 dfs序列&树状数组
- 【dfs序】【树状数组】bzoj1103 [POI2007]大都市meg
- bzoj 2819 Nim(BIT,dfs序,LCA)
- [dfs序 树状数组] BZOJ 1103 [POI2007]大都市meg