SPOJ10707 COT2 - Count on a tree II 【树上莫队】
题目分析:
考虑欧拉序,这里的欧拉序与ETT欧拉序的定义相同而与倍增LCA不同。然后不妨对于询问$u$与$v$让$dfsin[u] \leq dfsin[v]$,这样对于u和v不在一条路径上,它们可以改成询问$dfsin[u]$到$dfsin[v]$。否则改成$dfsout[u]$到$dfsin[v]$,并加上LCA上的影响,如果在询问过程中没有加入就加入,否则删除。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 40200; 5 const int maxm = 101000; 6 const int srt = 325; 7 8 int n,m; 9 int a[maxn],tb[maxn],arr[maxn],fa[maxn],pm[maxm],ans[maxm]; 10 int dfsin[maxn],dfsout[maxn],Num,pre[maxn]; 11 vector <int> g[maxn]; 12 vector <pair<int,int> > Qy[maxn]; 13 struct query{int l,r,bel,rem;}Q[maxm]; 14 15 int found(int x){ 16 int rx = x; while(pre[rx] != rx) rx = pre[rx]; 17 while(pre[x] != rx){int tmp = pre[x]; pre[x] = rx; x = tmp;} 18 return rx; 19 } 20 21 void dfs(int now,int ff){ 22 arr[now] = 1;pm[++Num] = now;fa[now] = ff; 23 dfsin[now] = Num; 24 for(int i=0;i<Qy[now].size();i++){ 25 if(!arr[Qy[now][i].first])continue; 26 Q[Qy[now][i].second].bel=found(Qy[now][i].first); 27 } 28 for(int i=0;i<g[now].size();i++){ 29 if(g[now][i]==fa[now])continue; 30 dfs(g[now][i],now); 31 } 32 pre[now] = fa[now]; 33 pm[++Num] = now; dfsout[now] = Num; 34 } 35 36 void read(){ 37 scanf("%d%d",&n,&m); 38 for(int i=1;i<=n;i++) scanf("%d",&a[i]),tb[i] = a[i]; 39 sort(tb+1,tb+n+1); int num=unique(tb+1,tb+n+1)-tb-1; 40 for(int i=1;i<=n;i++) a[i]=lower_bound(tb+1,tb+num+1,a[i])-tb; 41 memset(tb,0,sizeof(tb)); 42 for(int i=1;i<n;i++){ 43 int u,v; scanf("%d%d",&u,&v); 44 g[u].push_back(v); g[v].push_back(u); 45 } 46 for(int i=1;i<=m;i++) scanf("%d%d",&Q[i].l,&Q[i].r); 47 } 48 49 int cmp(query alpha,query beta){ 50 if(alpha.l/srt == beta.l/srt) return alpha.r < beta.r; 51 else return alpha.l/srt < beta.l/srt; 52 } 53 54 void init(){ 55 for(int i=1;i<=m;i++){ 56 Qy[Q[i].l].push_back(make_pair(Q[i].r,i)); 57 Qy[Q[i].r].push_back(make_pair(Q[i].l,i)); 58 } 59 for(int i=1;i<=n;i++) pre[i] = i; 60 dfs(1,0); 61 for(int i=1;i<=m;i++){ 62 if(dfsin[Q[i].l] > dfsin[Q[i].r]) swap(Q[i].l,Q[i].r); 63 if(Q[i].bel == Q[i].l || Q[i].bel == Q[i].r){ 64 Q[i].l = dfsin[Q[i].l]; Q[i].r = dfsin[Q[i].r]; 65 Q[i].bel = i; Q[i].rem = 0; 66 }else{ 67 Q[i].l = dfsout[Q[i].l]; Q[i].r = dfsin[Q[i].r]; 68 Q[i].rem = Q[i].bel; Q[i].bel = i; 69 } 70 } 71 sort(Q+1,Q+m+1,cmp); 72 } 73 74 void work(){ 75 int L = 1,R = 1,as=1; tb[a[1]]++; 76 for(int i=1;i<=m;i++){ 77 int nowl = Q[i].l,nowr = Q[i].r; 78 while(R < nowr){ 79 R++; 80 if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){ 81 if(!tb[a[pm[R]]])as++; 82 tb[a[pm[R]]]++; 83 }else{ 84 if(tb[a[pm[R]]] == 1) as--; 85 tb[a[pm[R]]]--; 86 } 87 } 88 while(L > nowl){ 89 L--; 90 if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){ 91 if(!tb[a[pm[L]]])as++; 92 tb[a[pm[L]]]++; 93 }else{ 94 if(tb[a[pm[L]]] == 1) as--; 95 tb[a[pm[L]]]--; 96 } 97 } 98 while(R > nowr){ 99 if(dfsin[pm[R]]==R||dfsin[pm[R]]<L){ 100 if(tb[a[pm[R]]] == 1) as--; 101 tb[a[pm[R]]]--; 102 }else{ 103 if(!tb[a[pm[R]]])as++; 104 tb[a[pm[R]]]++; 105 } 106 R--; 107 } 108 while(L < nowl){ 109 if(dfsout[pm[L]]==L||dfsout[pm[L]]>R){ 110 if(tb[a[pm[L]]] == 1) as--; 111 tb[a[pm[L]]]--; 112 }else{ 113 if(!tb[a[pm[L]]])as++; 114 tb[a[pm[L]]]++; 115 } 116 L++; 117 } 118 if(Q[i].rem && !tb[a[Q[i].rem]])ans[Q[i].bel]=as+1; 119 else ans[Q[i].bel] = as; 120 } 121 for(int i=1;i<=m;i++) printf("%d\n",ans[i]); 122 } 123 124 int main(){ 125 read(); 126 init(); 127 work(); 128 return 0; 129 }