2017瀋陽網路賽G XOR 分塊(分類討論sqrt)
阿新 • • 發佈:2018-12-01
題意:一棵樹,點權,Q次詢問,A---B路徑上每K個點的異或和
連結:點選開啟連結
思路:分類討論,k小於200,類似dp的預處理,在求lca的過程中可以求出來,k大於200,直接暴力跳,最多跳sqrtn步,其中還帶個log的倍增。1200ms AC。。
PS :場上手殘。。。
程式碼:
#include<bits/stdc++.h> using namespace std; const int MAXN = 100010; const int DEG = 20; int root; struct Edge{ int to,next; } edge[MAXN*2]; int head[MAXN],tot; void addedge(int u,int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } void init(){ tot = 0; memset(head,-1,sizeof(head)); } int fa[MAXN][DEG];//fa[i][j]表示結點i的第2^j個祖先 int deg[MAXN];//深度陣列 int w[MAXN]; int dp[MAXN][205]; int fa2[MAXN][205]; void BFS(int root){ queue<int>que; deg[root] = 0; fa[root][0] = root; que.push(root); while(!que.empty()){ int tmp = que.front(); que.pop(); for(int i = 1; i < DEG; i++) fa[tmp][i] = fa[fa[tmp][i-1]][i-1]; fa2[tmp][0]=tmp; for(int i = 1; i <= 200; i++) fa2[tmp][i]=fa2[fa[tmp][0]][i-1]; for(int i = 1; i <= 200; i++) dp[tmp][i]=dp[fa2[tmp][i]][i]^w[tmp]; for(int i = head[tmp]; i != -1; i = edge[i].next){ int v = edge[i].to; if(v == fa[tmp][0])continue; deg[v] = deg[tmp] + 1; fa[v][0] = tmp; que.push(v); } } } int LCA(int u,int v){ if(deg[u] > deg[v])swap(u,v); int hu = deg[u], hv = deg[v]; int tu = u, tv = v; for(int det = hv-hu, i = 0; det ; det>>=1, i++) if(det&1)tv = fa[tv][i]; if(tu == tv)return tu; for(int i = DEG-1; i >= 0; i--){ if(fa[tu][i] == fa[tv][i])continue; tu = fa[tu][i]; tv = fa[tv][i]; } return fa[tu][0]; } bool flag[MAXN]; int go(int x,int step){ for(int det = step, i = 0; det ; det>>=1, i++) if(det&1){ x = fa[x][i]; if(x==root) break; } return x; } int Sum(int x,int step){ int ret=w[x]; while(x!=root){ x=go(x,step); ret^=w[x]; } return ret; } int main(){ int T,N,Q; int u,v,k; while(scanf("%d%d",&N,&Q)!=EOF){ init(); memset(dp,0,sizeof(dp)); memset(w,0,sizeof(w)); for(int i = 1; i < N; i++){ scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } for(int i=1;i<=N;i++) scanf("%d",&w[i]); for(int i=1;i<=N;i++) addedge(N+i,N+i-1),addedge(N+i-1,N+i); root=N+N; BFS(root); for(int i=0;i<Q;i++){ scanf("%d%d%d",&u,&v,&k); int ans=0; if(u==v){ ans=w[u]; } else if(k<=200){ int lca=LCA(u,v); int lab=deg[u]+deg[v]-2*deg[lca]; int lalca=deg[u]-deg[lca]; int yu1=lalca%k,yu2=k-yu1,yu3=lab%k; ans=dp[u][k]^dp[go(lca,yu2)][k]^dp[go(v,yu3)][k]^dp[go(lca,yu1)][k]; } else{ int lca=LCA(u,v); int lab=deg[u]+deg[v]-2*deg[lca]; int lalca=deg[u]-deg[lca]; int yu1=lalca%k,yu2=k-yu1,yu3=lab%k; ans=Sum(u,k)^Sum(go(lca,yu2),k)^Sum(go(v,yu3),k)^Sum(go(lca,yu1),k); } printf("%d\n",ans); } } return 0; }