树上莫队 wowow

构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块。

 1 int dfs(int x){
 2     int size=0;
 3     dfn[x]=++ind;
 4     for (int i=1;i<=16;i++)
 5      if (bin[i]<=deep[x])
 6      fa[x][i]=fa[fa[x][i-1]][i-1];
 7      else break;
 8     for (int i=first[x];i;i=next[i]){
 9         int pur=go[i];
10         if (pur!=fa[x][0]){
11             fa[pur][0]=x;
12             deep[pur]=deep[x]+1;
13             size+=dfs(pur);
14             if (size>=blo){
15                 blonum++;
16                 for (int k=1;k<=size;k++)
17                  belong[st[top--]]=blonum;
18                 size=0; 
19             }
20         }
21     }
22     st[++top]=x;
23     return size+1;
24 }

然后呢,我们可以发现一些树上莫队的性质:

用S(v, u)代表 v到u的路径上的结点的集合。
用root来代表根结点,用lca(v, u)来代表v、u的最近公共祖先。
那么
S(v, u) = S(root, v) xor S(root, u) xor lca(v, u)
其中xor是集合的对称差。
简单来说就是节点出现两次消掉。
lca很讨厌,于是再定义
T(v, u) = S(root, v) xor S(root, u)
观察将curV移动到targetV前后T(curV, curU)变化:
T(curV, curU) = S(root, curV) xor S(root, curU)
T(targetV, curU) = S(root, targetV) xor S(root, curU)
取对称差:
T(curV, curU) xor T(targetV, curU)= (S(root, curV) xor S(root, curU)) xor (S(root, targetV) xor S(root, curU))
由于对称差的交换律、结合律:
T(curV, curU) xor T(targetV, curU)= S(root, curV) xorS(root, targetV)
两边同时xor T(curV, curU):
T(targetV, curU)= T(curV, curU) xor S(root, curV) xor S(root, targetV)
T(targetV, curU)= T(curV, curU) xor T(curV, targetV)
也就是说,更新的时候,xor T(curV, targetV)就行了。
即,对curV到targetV路径(除开lca(curV, targetV))上的结点,将它们的存在性取反即可。
 
按照以上方式,我们就可以每次从u1走到u2,v1走到v2,然后要求query的时候对他们的公共祖先的存在性取反,然后求完答案后再取反回去。
 
bzoj3757 苹果树
  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <string>
  6 #include <queue>
  7 #include <stack>
  8 #include <cmath>
  9 #include <map>
 10 #include <vector>
 11 #include <functional>
 12 #include <ctime>
 13 #include <cstdlib>
 14 #include <sstream>
 15 #include <set>
 16 #include <deque>
 17 #define Rep(i, l, r) for (int i = l; i <= r; ++i)
 18 #define Req(i, l, r) for (int i = l; i >= r; --i)
 19 #define N 100005
 20 int tot,go[N],next[N],first[N],dfn[N],belong[N];
 21 int st[N],res[N],n,m,x,y,fa[N][20],bin[20],col[N],ans,ind,deep[N],blo,blonum;
 22 int top,pd[N],root;
 23 struct op{
 24     int u,v,id,a,b;
 25 }q[N];
 26 int p[N];
 27 void insert(int x,int y){
 28     tot++;
 29     go[tot]=y;
 30     next[tot]=first[x];
 31     first[x]=tot;
 32 }
 33 void add(int x,int y){
 34     insert(x,y);
 35     insert(y,x);
 36 }
 37 bool cmp(op q,op w){
 38     if (belong[q.u]==belong[w.u]) return dfn[q.v]<dfn[w.v];
 39     else return belong[q.u]<belong[w.u];
 40 }
 41 int dfs(int x){
 42     int size=0;
 43     dfn[x]=++ind;
 44     for (int i=1;i<=16;i++)
 45      if (bin[i]<=deep[x])
 46      fa[x][i]=fa[fa[x][i-1]][i-1];
 47      else break;
 48     for (int i=first[x];i;i=next[i]){
 49         int pur=go[i];
 50         if (pur!=fa[x][0]){
 51             fa[pur][0]=x;
 52             deep[pur]=deep[x]+1;
 53             size+=dfs(pur);
 54             if (size>=blo){
 55                 blonum++;
 56                 for (int k=1;k<=size;k++)
 57                  belong[st[top--]]=blonum;
 58                 size=0; 
 59             }
 60         }
 61     }
 62     st[++top]=x;
 63     return size+1;
 64 }
 65 void reverse(int x){
 66     if (pd[x]) {
 67         p[col[x]]--;
 68         pd[x]=0;
 69         if (p[col[x]]==0) ans--;
 70     }
 71     else{
 72         p[col[x]]++;
 73         pd[x]=1;
 74         if (p[col[x]]==1) ans++;
 75     }
 76 }
 77 void solve(int u,int v){
 78     while (u!=v){
 79         if (deep[u]>deep[v]) reverse(u),u=fa[u][0];
 80         else reverse(v),v=fa[v][0];
 81     }
 82 }
 83 int lca(int x,int y){
 84     if (deep[x]<deep[y]) std::swap(x,y);
 85     int t=deep[x]-deep[y];
 86     for (int i=19;i>=0;i--)
 87      if (t&bin[i]){
 88         x=fa[x][i];
 89      }
 90     for (int i=19;i>=0;i--)
 91      if (fa[x][i]!=fa[y][i]){
 92         x=fa[x][i];
 93         y=fa[y][i];
 94      } 
 95     if (x==y) return x;
 96     else return fa[x][0]; 
 97 }
 98 int main(){
 99     bin[0]=1;
100     for (int i=1;i<20;i++) bin[i]=bin[i-1]*2;
101     scanf("%d%d",&n,&m);
102     blo=sqrt(n);
103     for (int i=1;i<=n;i++)
104      scanf("%d",&col[i]);
105     for (int i=1;i<=n;i++){
106         scanf("%d%d",&x,&y);
107         if (x==0)
108             root=y;
109         else
110         if (y==0)
111             root=x;
112         else   
113         add(x,y);
114     } 
115     dfs(root);
116     blonum++;
117     while (top) belong[st[top--]]=blonum;
118     for (int i=1;i<=m;i++){
119         scanf("%d%d",&q[i].u,&q[i].v);
120         if (dfn[q[i].u]>dfn[q[i].v]) std::swap(q[i].v,q[i].u);
121         scanf("%d%d",&q[i].a,&q[i].b);
122         q[i].id=i;
123     }
124     std::sort(q+1,q+1+m,cmp);
125     int t=lca(q[1].u,q[1].v);
126     solve(q[1].u,q[1].v);
127     reverse(t);
128     res[q[1].id]=ans;
129     if (p[q[1].a]&&p[q[1].b]&&q[1].a!=q[1].b) res[q[1].id]--;
130     reverse(t);
131     for (int i=2;i<=m;i++){
132         solve(q[i-1].u,q[i].u);
133         solve(q[i-1].v,q[i].v);
134         t=lca(q[i].u,q[i].v);
135         reverse(t);
136         res[q[i].id]=ans;
137         if (p[q[i].a]&&p[q[i].b]&&q[i].a!=q[i].b) res[q[i].id]--;
138         reverse(t);
139     }
140     for (int i=1;i<=m;i++)
141      printf("%d
",res[i]);
142 }
bzoj3052 WC糖果公园
  1  
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <string>
  7 #include <queue>
  8 #include <stack>
  9 #include <cmath>
 10 #include <map>
 11 #include <vector>
 12 #include <functional>
 13 #include <ctime>
 14 #include <cstdlib>
 15 #include <sstream>
 16 #include <set>
 17 #include <deque>
 18 #define Rep(i, l, r) for (int i = l; i <= r; ++i)
 19 #define Req(i, l, r) for (int i = l; i >= r; --i)
 20 #define N 200005
 21 long long res[N];
 22 long long pre[N],col[N],v[N],w[N],ans;
 23 int belong[N],go[N],tot,first[N],next[N];
 24 int deep[N],bin[20],fa[N][17],st[N],top,x,y,n,m,c1,c2,dfn[N],ind,blo,blonum;
 25 int pd[N],p[N],qe,ty;
 26 struct op{
 27     int x,y,id,t;
 28     long long pre;
 29 }c[N],b[N];
 30 bool cmp(op a,op b){
 31     if (belong[a.x]==belong[b.x]&&belong[a.y]==belong[b.y]) return a.t<b.t;
 32     else
 33     if (belong[a.x]==belong[b.x]) return belong[a.y]<belong[b.y];
 34     return belong[a.x]<belong[b.x];
 35 }
 36 void insert(int x,int y){
 37     tot++;
 38     go[tot]=y;
 39     next[tot]=first[x];
 40     first[x]=tot;
 41 }
 42 void add(int x,int y){
 43     insert(x,y);
 44     insert(y,x);
 45 }
 46 int dfs(int x){
 47     int size=0;
 48     dfn[x]=++ind;
 49     for (int i=1;i<=16;i++)
 50      if (deep[x]>=bin[i])
 51       fa[x][i]=fa[fa[x][i-1]][i-1];
 52      else break; 
 53     for (int i=first[x];i;i=next[i]){
 54         int pur=go[i];
 55         if (pur!=fa[x][0]){
 56             fa[pur][0]=x;
 57             deep[pur]=deep[x]+1;
 58             size+=dfs(pur);
 59             if (size>=blo){
 60                 blonum++;
 61                 for (int j=1;j<=size;j++)
 62                  belong[st[top--]]=blonum;
 63                 size=0; 
 64             }
 65         }
 66     }  
 67     st[++top]=x;
 68     return size+1;
 69 }
 70 void reverse(int x){
 71     if (pd[x]){
 72         ans-=w[p[col[x]]]*v[col[x]];
 73         p[col[x]]--;
 74         pd[x]=0;
 75     }
 76     else{
 77         pd[x]=1;
 78         p[col[x]]++;
 79         ans+=w[p[col[x]]]*v[col[x]];
 80     }
 81 }
 82 void change(int x,int y){
 83     if (pd[x]){
 84         reverse(x);
 85         col[x]=y;
 86         reverse(x);
 87     }
 88     else{
 89         col[x]=y;
 90     }
 91 }
 92 void solve(int x,int y){
 93     while (x!=y){
 94         if (deep[x]>deep[y]) reverse(x),x=fa[x][0];
 95         else reverse(y),y=fa[y][0];
 96     }
 97 }
 98 int lca(int x,int y){
 99     if (deep[x]<deep[y]) std::swap(x,y);
100     int t=deep[x]-deep[y];
101     for (int i=16;i>=0;i--)
102      if (t&bin[i])
103       x=fa[x][i];
104     for (int i=16;i>=0;i--)
105      if (fa[x][i]!=fa[y][i])
106       x=fa[x][i],y=fa[y][i];
107     if (x==y) return x;
108     else return fa[x][0];    
109 }
110 int main(){
111     //freopen("tx.txt","r",stdin);
112     bin[0]=1;
113     for (int i=1;i<=17;i++) bin[i]=bin[i-1]*2;
114     scanf("%d%d%d",&n,&m,&qe);
115     blo=pow(n,2.0/3)*0.5;
116     for (int i=1;i<=m;i++)
117      scanf("%lld",&v[i]);
118     for (int i=1;i<=n;i++)
119      scanf("%lld",&w[i]);
120     for (int i=1;i<n;i++){
121         scanf("%d%d",&x,&y);
122         add(x,y);
123     }  
124     for (int i=1;i<=n;i++){
125      scanf("%lld",&col[i]);
126      pre[i]=col[i];
127      }
128     dfs(1); 
129     //blonum++;
130     while (top) belong[st[top--]]=blonum;
131     for (int i=1;i<=qe;i++){
132         scanf("%d",&ty);
133         if (!ty){
134             c1++;
135             scanf("%d%d",&c[c1].x,&c[c1].y);
136             c[c1].pre=pre[c[c1].x];
137             pre[c[c1].x]=c[c1].y;
138         }
139         else{
140             c2++;
141             scanf("%d%d",&b[c2].x,&b[c2].y);
142             b[c2].t=c1;
143             if (dfn[b[c2].x]>dfn[b[c2].y]) std::swap(b[c2].x,b[c2].y);
144             b[c2].id=c2;
145         }
146     }
147     std::sort(b+1,b+1+c2,cmp);
148     for (int i=1;i<=b[1].t;i++)
149      change(c[i].x,c[i].y);
150     solve(b[1].x,b[1].y);
151     int t=lca(b[1].x,b[1].y);
152     reverse(t);
153     res[b[1].id]=ans;
154     reverse(t);
155     for (int i=2;i<=c2;i++){
156         for (int j=b[i-1].t+1;j<=b[i].t;j++)
157          change(c[j].x,c[j].y);
158         for (int j=b[i-1].t;j>b[i].t;j--)
159          change(c[j].x,c[j].pre); 
160         solve(b[i-1].x,b[i].x);
161         solve(b[i-1].y,b[i].y);
162         int t=lca(b[i].x,b[i].y);
163         reverse(t); 
164         res[b[i].id]=ans;
165         reverse(t);
166     } 
167     for (int i=1;i<=c2;i++)
168      printf("%lld
",res[i]);
169 }
170 
原文地址:https://www.cnblogs.com/qzqzgfy/p/5266696.html