标签:
1 3 2 1 2 2 3 1 1 1 1 1 2 1 1 3
-1 1HintIf you want to hack someone,N and Q in your testdata must smaller than 10000,and you shouldn‘t print any space in each end of the line.
大致题意:
一棵树1e5节点的树,有1e5次两种操作,修改某点的权值,询问两点间的路径上的每个权值是否都是偶数个,若不是输出奇数个的权值大小,保证询问的路径上最多只有一个权值是奇数个
思路:
方法1.维护每个点到根的异或,然后查询就是xor[u]^xor[v]^LCA(u,v)
更新操作:更新某个点显然此点的子树的xor到根的异或都会更新,所以用dfs记录进入节点和退出节点的时间戳,把时间戳作为节点映射到线段树上(所以个数是数节点的两倍),然后成段更新进入此节点到退出此节点的时间戳的区间即可
复杂度是nlogn
方法2:
正面上,询问就是两个点间的路径的异或,即树链剖分
复杂度n*logn*logn
方法一:
#include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <list> #include <map> #include <set> #include <sstream> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) using namespace std; typedef long long ll; const int N = 1e5+100; int n,Q; int indx; struct Edge { int v,nxt; Edge(){} Edge(int v,int nxt):v(v),nxt(nxt){} }es[N<<1]; int head[N],ecnt; inline void add_edge(int v,int u) { es[ecnt] = Edge(v,head[u]); head[u] = ecnt++; es[ecnt] = Edge(u,head[v]); head[v] = ecnt++; } int val[N]; //.................................... #define root 1,indx,1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int XOR[N<<2]; inline void pushup(int rt) { XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1]; } void update(int pos,int x,int l,int r,int rt) { if(l == r) { XOR[rt] ^= x; return ; } int m = (l+r)>>1; if(pos <= m) update(pos,x,lson); else update(pos,x,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt) { if(L <= l && r <= R) return XOR[rt]; int m = (l+r)>>1; int ans = 0; if(L <= m) ans ^= query(L,R,lson); if(R > m) ans ^= query(L,R,rson); return ans; } //................................. int dep[N],hvyson[N],sz[N],fa[N]; void dfs1(int u) { dep[u] = dep[fa[u]]+1; hvyson[u] = 0,sz[u] = 1; for(int i = head[u];~i;i = es[i].nxt) { int v = es[i].v; if(v == fa[u]) continue; fa[v] = u; dfs1(v); sz[u] += sz[v]; if(sz[v] > sz[hvyson[u]]) hvyson[u] = v; } } int tp[N],tid[N]; void dfs2(int u,int ance) { tid[u] = ++indx; tp[u] = ance; if(hvyson[u]) dfs2(hvyson[u],ance); for(int i = head[u];~i;i = es[i].nxt) { int v = es[i].v; if(v == fa[u]) continue; if(v != hvyson[u])dfs2(v,v); } } int ask(int u,int v) { int anceu = tp[u],ancev = tp[v]; int ans = 0; while(anceu != ancev) { if(dep[anceu] < dep[ancev]) swap(anceu,ancev),swap(u,v); ans ^= query(tid[anceu],tid[u],root); u = fa[anceu]; anceu = tp[u]; } if(u == v) return ans ^= val[u]; if(dep[u] < dep[v]) return ans ^= query(tid[u],tid[v],root); else return ans ^= query(tid[v],tid[u],root); } //.................................. void ini() { ecnt = indx = 0; memset(head,-1,sizeof(head)); memset(XOR,0,sizeof(XOR)); } int main() { int T; scanf("%d",&T); while(T--) { ini(); scanf("%d%d",&n,&Q); REP(i,n-1) { int u,v; scanf("%d%d",&u,&v); add_edge(u,v); } REP(i,n) scanf("%d",&val[i]),val[i]++; dfs1(1); dfs2(1,1); REP(i,n) update(tid[i],val[i],root); REP(i,Q) { int op; scanf("%d",&op); if(op == 0) { int u,x; scanf("%d%d",&u,&x);x++; update(tid[u],val[u]^x,root); val[u] = x; } else { int u,v; scanf("%d%d",&u,&v); printf("%d\n",ask(u,v)-1); } } } }
方法二:
//312MS 21660K 4306 B C++ #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstring> #include <cmath> #include <queue> #include <stack> #include <list> #include <map> #include <set> #include <sstream> #include <string> #include <vector> #include <cstdio> #include <ctime> #include <bitset> #include <algorithm> #define SZ(x) ((int)(x).size()) #define ALL(v) (v).begin(), (v).end() #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i) #define REP(i,n) for ( int i=1; i<=int(n); i++ ) using namespace std; typedef long long ll; const int N = 1e5+100; int n,Q; struct Edge { int v,nxt; Edge(){} Edge(int v,int nxt) : v(v),nxt(nxt){} }es[N*2]; int ecnt,head[N]; inline void add_edge(int u,int v) { es[ecnt] = Edge(v,head[u]); head[u] = ecnt++; es[ecnt] = Edge(u,head[v]); head[v] = ecnt++; } int val[N]; //................................... int indx,st[N],ed[N],vs[N<<1]; int dp[N]; void dfs(int u,int fa) { dp[u] = dp[fa]^val[u]; st[u] = ++indx; vs[indx] = u; for(int i = head[u];~i;i = es[i].nxt) { int v = es[i].v; if(v == fa) continue; dfs(v,u); } ed[u] = ++indx; vs[indx] = u; } //............................... int dep[N]; bool vis[N]; int pa[N][20]; void bfs() { queue<int>q; q.push(1); pa[1][0]=1; vis[1]=1; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1]; for(int i=head[u];~i;i=es[i].nxt) { int v=es[i].v; if(vis[v]==0) { vis[v]=1; pa[v][0]=u; dep[v]=dep[u]+1; q.push(v); } } } } int LCA(int u,int v) { if(dep[u]>dep[v]) swap(u,v); for(int det=dep[v]-dep[u],i=0;det;i++,det>>=1) if(det&1) v=pa[v][i]; if(v==u) return v; for(int i=20-1;i>=0;i--) if(pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i]; return pa[u][0]; } //............................... int XOR[(N<<1)<<2],col[(N<<1)<<2]; #define root 1,indx,1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 inline void pushup(int rt) { XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1]; } inline void pushdown(int rt) { if(col[rt] == 0) return ; col[rt<<1] ^= col[rt]; col[rt<<1|1] ^= col[rt]; XOR[rt<<1] ^= col[rt]; XOR[rt<<1|1] ^= col[rt]; col[rt] = 0; } void build(int l,int r,int rt) { if(l == r) { XOR[rt] = dp[vs[l]]; col[rt] = 0; return ; } int m = (l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int L,int R,int x,int l,int r,int rt) { if(L <= l && r <= R) { XOR[rt] ^= x; col[rt] ^= x; return ; } pushdown(rt); int m = (l+r)>>1; if(L <= m) update(L,R,x,lson); if(R > m) update(L,R,x,rson); pushup(rt); } int query(int pos,int l,int r,int rt) { if(l == r) return XOR[rt]; pushdown(rt); int m = (l+r)>>1; if(pos <= m) return query(pos,lson); else return query(pos,rson); } //.............................. void ini() { indx = ecnt = 0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); } int main() { int T; scanf("%d",&T); while(T--) { ini(); scanf("%d%d",&n,&Q); REP(i,n-1) { int u,v; scanf("%d%d",&u,&v); add_edge(u,v); } REP(i,n) scanf("%d",&val[i]),val[i]++; dfs(1,0); bfs(); build(root); while(Q--) { int op; scanf("%d",&op); if(op == 0) { int u,x; scanf("%d%d",&u,&x); x++; update(st[u],ed[u],val[u]^x,root); val[u] = x; } else { int u,v; scanf("%d%d",&u,&v); int ans = query(ed[u],root)^query(ed[v],root)^val[LCA(u,v)]; printf("%d\n",ans-1); } } } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)
标签:
原文地址:http://blog.csdn.net/kalilili/article/details/46999415