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 }

 

posted @ 2018-08-28 07:55  menhera  阅读(271)  评论(0编辑  收藏  举报