Count on a tree II SPOJ - COT2 && bzoj1086 王室联邦 && bzoj2589

https://cn.vjudge.net/problem/SPOJ-COT2

这个是树上莫队模版啊。。

树上莫队有两种,第一种就是括号序莫队

设节点i在括号序中首次出现位置为pl[i]

那么路径(i,j)上的节点,相当于括号序中pl[i]到pl[j]中所有只出现1次的节点,可能还要加上i,j,lca(i,j)

更精确的描述:https://blog.csdn.net/xianhaoming/article/details/52201761

这样很容易用序列莫队+lca(i,j),i,j的特判解决

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<map>
  6 using namespace std;
  7 #define fi first
  8 #define se second
  9 #define mp make_pair
 10 #define pb push_back
 11 typedef long long ll;
 12 typedef unsigned long long ull;
 13 typedef pair<int,int> pi;
 14 int n,m;
 15 int a[40100];
 16 vector<int> e[40100];
 17 struct Q
 18 {
 19     int x,y,n;
 20 }q[100100];
 21 int sz=225;
 22 int d[80100],pl[40100],bl[80100];
 23 bool vis[40100];
 24 int ans[100100],num[40100],an;
 25 int t1[40100];
 26 int anc[40100][20],dep[40100],l2n=19;
 27 map<int,int> ma;
 28 void dfs(int u,int fa)
 29 {
 30     int i;
 31     d[++d[0]]=u;pl[u]=d[0];
 32     anc[u][0]=fa;
 33     dep[u]=dep[fa]+1;
 34     for(i=1;i<=l2n;i++)
 35         anc[u][i]=anc[anc[u][i-1]][i-1];
 36     for(i=0;i<e[u].size();i++)
 37         if(e[u][i]!=fa)
 38             dfs(e[u][i],u);
 39     d[++d[0]]=u;
 40 }
 41 int lca(int x,int y)
 42 {
 43     int t,i;
 44     if(dep[x]<dep[y]){t=x;x=y;y=t;}
 45     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
 46         if(t&1)    x=anc[x][i];
 47     if(x==y)    return x;
 48     for(i=l2n;i>=0;i--)
 49         if(anc[x][i]!=anc[y][i])
 50         {
 51             x=anc[x][i];
 52             y=anc[y][i];
 53         }
 54     return anc[x][0];
 55 }
 56 bool operator<(const Q &a,const Q &b)
 57 {
 58     return bl[a.x]==bl[b.x]?a.y<b.y:a.x<b.x;
 59 }
 60 void change(int u)
 61 {
 62     if(vis[u])
 63     {
 64         num[a[u]]--;
 65         if(num[a[u]]==0)    an--;
 66         vis[u]=0;
 67     }
 68     else
 69     {
 70         if(num[a[u]]==0)    an++;
 71         num[a[u]]++;
 72         vis[u]=1;
 73     }
 74 }
 75 int main()
 76 {
 77     int i,u,v;
 78     scanf("%d%d",&n,&m);
 79     for(i=1;i<=n;i++)    scanf("%d",&a[i]),t1[++t1[0]]=a[i];
 80     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
 81     for(i=1;i<=t1[0];i++)    ma[t1[i]]=i;
 82     for(i=1;i<=n;i++)    a[i]=ma[a[i]];
 83     
 84     //for(i=1;i<=n;i++)    printf("a%d %d\n",i,a[i]);
 85     for(i=1;i<n;i++)
 86     {
 87         scanf("%d%d",&u,&v);
 88         e[u].pb(v);e[v].pb(u);
 89     }
 90     dfs(1,0);
 91     for(i=1;i<=m;i++)
 92     {
 93         scanf("%d%d",&q[i].x,&q[i].y);
 94         q[i].x=pl[q[i].x];q[i].y=pl[q[i].y];
 95         if(q[i].x>q[i].y)    swap(q[i].x,q[i].y);
 96         q[i].n=i;
 97     }
 98     //putchar('a');
 99     //for(i=1;i<=d[0];i++)    printf("%d ",d[i]);
100     //puts("");
101     for(i=1;i<=d[0];i++)    bl[i]=(i-1)/sz;
102     sort(q+1,q+m+1);
103     int l=1,r=0;
104     for(i=1;i<=m;i++)
105     {
106         while(l>q[i].x)    change(d[--l]);
107         while(r<q[i].y)    change(d[++r]);
108         while(l<q[i].x)    change(d[l++]);
109         while(r>q[i].y)    change(d[r--]);
110         bool fl1=vis[d[q[i].x]],fl2=vis[d[q[i].y]];
111         int ll=lca(d[q[i].x],d[q[i].y]);
112         bool fl3=vis[ll];
113         //printf("b%d %d %d %d %d %d\n",q[i].x,q[i].y,ll,fl1,fl2,fl3);
114         if(!fl1)    change(d[q[i].x]);
115         if(!fl2)    change(d[q[i].y]);
116         if(!fl3)    change(ll);
117         ans[q[i].n]=an;
118         if(!fl1)    change(d[q[i].x]);
119         if(!fl2)    change(d[q[i].y]);
120         if(!fl3)    change(ll);
121     }
122     for(i=1;i<=m;i++)    printf("%d\n",ans[i]);
123     return 0;
124 }

还有一种是树分块后直接做莫队

树分块的方法很多,按我自己的理解,此时可行的分块方法要求块内部任意两点间距离不超过根号级别,且各个块按照“块树”的dfs序排列(由这个顺序得到块编号)(不确定)

这样子的话,将所有询问以左端点的块编号为第一关键字,右端点的块编号为第二关键字,排序所有询问,

每一次转移的时候,两个端点都变了,但是可以当成一个端点一个端点的变;从(u,v1)的答案变到(u,v2)的答案,就是除了以u为根时lca(v1,v2)以外,对(v1,v2)的路径上所有点的“是否在当前答案中”属性取反(划掉的东西我不会证也不想维护)

根据一些证明,只要首先丢掉每个询问的两个端点的lca(处理这个询问时临时加上就行了),那么从(u,v1)变到(u,v2),只要对(v1,v2)路径上所有点(除了lca)的“是否在当前答案中”属性取反就行了

证明:https://www.cnblogs.com/RabbitHu/p/MoDuiTutorial.html

树分块方法:

(对于方法:如果某个节点父亲所在的块加上自己所在的块大小没超过K(指定的最大块大小),那么将这两个块合并(一般K就取sqrt(n))

能保证块大小,不能保证块数。。。

听说菊花图能卡掉。。。然而想了很久,也没想出来什么样的菊花图能卡掉这个方法的树上莫队

算了,还是不用了)

1.王室联邦分块

https://www.lydsy.com/JudgeOnline/problem.php?id=1086

做法:https://www.cnblogs.com/shenben/p/6368457.html

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define fi first
 7 #define se second
 8 #define mp make_pair
 9 #define pb push_back
10 typedef long long ll;
11 typedef unsigned long long ull;
12 typedef pair<int,int> pii;
13 int n,sz;
14 vector<int> e[100100];
15 int st[100100],tp,rt[100100],cnt,bl[100100];
16 void dfs(int u,int fa)
17 {
18     int i,ltp=tp;
19     for(i=0;i<e[u].size();i++)
20         if(e[u][i]!=fa)
21         {
22             dfs(e[u][i],u);
23             if(tp-ltp>=sz)
24             {
25                 rt[++cnt]=u;
26                 while(tp!=ltp)    bl[st[tp--]]=cnt;
27             }
28         }
29     st[++tp]=u;
30 }
31 int main()
32 {
33     int i,a,b;
34     scanf("%d%d",&n,&sz);
35     for(i=1;i<n;i++)
36     {
37         scanf("%d%d",&a,&b);
38         e[a].pb(b);e[b].pb(a);
39     }
40     dfs(1,0);
41     while(tp)    bl[st[tp--]]=cnt;
42     printf("%d\n",cnt);
43     for(i=1;i<=n;i++)    printf("%d ",bl[i]);
44     puts("");
45     for(i=1;i<=cnt;i++)    printf("%d ",rt[i]);
46     return 0;
47 }

 

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<map>
  6 #include<cmath>
  7 using namespace std;
  8 #define fi first
  9 #define se second
 10 #define mp make_pair
 11 #define pb push_back
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<int,int> pii;
 15 int n,sz,m;
 16 vector<int> e[100100];
 17 int st[100100],tp,rt[100100],cnt,bl[100100];
 18 int dd[100100];
 19 struct Q
 20 {
 21     int x,y,n;
 22 }q[100100];
 23 void dfs(int u,int fa)
 24 {
 25     int i,ltp=tp;
 26     for(i=0;i<e[u].size();i++)
 27         if(e[u][i]!=fa)
 28         {
 29             dfs(e[u][i],u);
 30             if(tp-ltp>=sz)
 31             {
 32                 rt[++cnt]=u;
 33                 while(tp!=ltp)    bl[st[tp--]]=cnt;
 34             }
 35         }
 36     st[++tp]=u;
 37 }
 38 bool operator<(const Q &a,const Q &b)
 39 {
 40     return bl[a.x]==bl[b.x]?bl[a.y]<bl[b.y]:bl[a.x]<bl[b.x];
 41 }
 42 int num[100100],an;
 43 bool vis[100100];
 44 void change(int u)
 45 {
 46     if(vis[u])
 47     {
 48         num[dd[u]]--;
 49         if(num[dd[u]]==0)    an--;
 50         vis[u]=0;
 51     }
 52     else
 53     {
 54         if(num[dd[u]]==0)    an++;
 55         num[dd[u]]++;
 56         vis[u]=1;
 57     }
 58 }
 59 namespace LCA
 60 {
 61 int anc[100100][20],dep[100100],l2n=19;
 62 void dfs(int u,int fa)
 63 {
 64     int i;
 65     anc[u][0]=fa;
 66     dep[u]=dep[fa]+1;
 67     for(i=1;i<=l2n;i++)
 68         anc[u][i]=anc[anc[u][i-1]][i-1];
 69     for(i=0;i<e[u].size();i++)
 70         if(e[u][i]!=fa)
 71             dfs(e[u][i],u);
 72 }
 73 int lca(int x,int y)
 74 {
 75     int t,i;
 76     if(dep[x]<dep[y]){t=x;x=y;y=t;}
 77     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
 78         if(t&1)    x=anc[x][i];
 79     if(x==y)    return x;
 80     for(i=l2n;i>=0;i--)
 81         if(anc[x][i]!=anc[y][i])
 82         {
 83             x=anc[x][i];
 84             y=anc[y][i];
 85         }
 86     return anc[x][0];
 87 }
 88 void work(int x,int y)
 89 {
 90     if(dep[x]<dep[y])    swap(x,y);
 91     while(dep[x]>dep[y])
 92     {
 93         change(x);
 94         x=anc[x][0];
 95     }
 96     while(x!=y)
 97     {
 98         change(x);change(y);
 99         x=anc[x][0];y=anc[y][0];
100     }
101 }
102 }
103 using LCA::work;
104 using LCA::lca;
105 int t1[100100];
106 map<int,int> ma;
107 int ans[100100];
108 int main()
109 {
110     int i,a,b,l;
111     scanf("%d%d",&n,&m);sz=sqrt(n+0.5);
112     if(m==0)    return 0;
113     for(i=1;i<=n;i++)    scanf("%d",&dd[i]),t1[++t1[0]]=dd[i];
114     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
115     for(i=1;i<=t1[0];i++)    ma[t1[i]]=i;
116     for(i=1;i<=n;i++)    dd[i]=ma[dd[i]];
117     for(i=1;i<n;i++)
118     {
119         scanf("%d%d",&a,&b);
120         e[a].pb(b);e[b].pb(a);
121     }
122     dfs(1,0);LCA::dfs(1,0);
123     while(tp)    bl[st[tp--]]=cnt;
124     for(i=1;i<=m;i++)
125     {
126         scanf("%d%d",&q[i].x,&q[i].y);
127         q[i].n=i;
128     }
129     sort(q+1,q+m+1);
130     work(q[1].x,q[1].y);
131     l=lca(q[1].x,q[1].y);
132     change(l);
133     ans[q[1].n]=an;
134     change(l);
135     for(i=2;i<=m;i++)
136     {
137         work(q[i].x,q[i-1].x);
138         work(q[i].y,q[i-1].y);
139         l=lca(q[i].x,q[i].y);
140         change(l);
141         ans[q[i].n]=an;
142         change(l);
143     }
144     for(i=1;i<=m;i++)    printf("%d\n",ans[i]);
145     return 0;
146 }

https://www.lydsy.com/JudgeOnline/problem.php?id=2589

加强版啊。。强制在线啊

更麻烦了,不能用莫队了

不过做过强制在线区间众数,还是有一点类似的

随便搞一个根节点(比如1),分块

处理一些东西:

fa[i]表示i的父亲

rt[i]表示i块的“块顶”

bl[i]表示i节点所属块

an1[i][j]:rt[i],rt[j]间答案(除lca(rt[i],rt[j]))

d[i][j]:rt[i]到树根的路径中权值为j的有多少个

vv[i][j]:j是否在rt[i]到根的路径上

对于询问(a,b),

设ra=rt[bl[a]],rb=rt[bl[b]]

先得到ra,rb路径上的答案(除lca(ra,rb))(这个答案已经预处理出来了)

然后假装你得到了两个数组tt和vis,其中tt[i]表示ra到rb的路径上(除lca),权值i出现的次数;vis[i]表示i是否在ra到rb的路径上(除lca)

(你当然没有得到这两个数组,但是设l=lca(ra,rb),那么预处理一些东西后,这两个数组的任一个元素都可以O(1)得到)

(每一次询问时,先求出gt[i]为l到rt[bl[l]]的路径上(含l,不含rt[bl[l]])权值i出现的次数)

(那么tt[i]=d[bl[a]][i]+d[bl[b]][i]-2*d[bl[l]][i]-2*gt[i],vis[i]=vv[bl[a]][i]^vv[bl[b]][i])

按照莫队的方法转移就行了,最后把lca临时加上

(显然不能直接修改,要另开空数组记录修改,得到答案后把修改还原)

听说这种类型的分块(记录两块间答案的)也可以通过调整块大小支持带修复杂度n^(5/3)?以后再说

理想很美好,现实很...

我卡常失败了,本地(破机子)一个点10秒,随便找个别的机子一个点4-5秒,测了一下运算次数,大概有30亿,跟暴力差不多。。。不知道是不是写错了;在"别的机子"上,强制在线莫队大概7秒,所以应该还好吧...

调了一个下午啊,以后再说吧

试验中可能有效的卡常:

1.修改时把修改的用另一个数组记录下来,后面根据记下的信息还原(直接置0),而不是反着做一遍,还原时可以用指针

2.261行之前把bl[a],bl[b],bl[l]用单独的变量先取出来,后面直接使用

3.261行乘号改左移;快读快写

失败代码:

错误记录:

1.分块的时候要注意,最后剩下的一部分,要么加入最后一块,额外使得rt[cnt]=1,要么另开一块,使得rt[cnt]=1;跟前面不一样

2.各种dd[x],x,bl[x]不分,代码中打了注释的就是错误记录

3.一开始没考虑(以上说明中)gt的贡献

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<map>
  7 #include<cmath>
  8 //#include<cassert>
  9 using namespace std;
 10 #define fi first
 11 #define se second
 12 #define mp make_pair
 13 #define pb push_back
 14 typedef long long ll;
 15 typedef unsigned long long ull;
 16 typedef pair<int,int> pii;
 17 int n,sz,m;
 18 vector<int> e[40100];
 19 int rt[40100],cnt,bl[40100];
 20 namespace GBLOCK
 21 {
 22 int st[40100],tp;
 23 void dfs(int u,int fa)
 24 {
 25     int i,ltp=tp;
 26     for(i=0;i<e[u].size();i++)
 27         if(e[u][i]!=fa)
 28         {
 29             dfs(e[u][i],u);
 30             if(tp-ltp>=sz)
 31             {
 32                 rt[++cnt]=u;
 33                 while(tp!=ltp)    bl[st[tp--]]=cnt;
 34             }
 35         }
 36     st[++tp]=u;
 37 }
 38 void work()
 39 {
 40     dfs(1,0);
 41     //assert(rt[cnt]==1);
 42     ++cnt;rt[cnt]=1;
 43     while(tp)    bl[st[tp--]]=cnt;
 44 }
 45 }
 46 int dd[40100];
 47 namespace LCA
 48 {
 49 int anc[40100][20],dep[40100],l2n=19;
 50 void dfs(int u,int fa)
 51 {
 52     int i;
 53     anc[u][0]=fa;
 54     dep[u]=dep[fa]+1;
 55     for(i=1;i<=l2n;i++)
 56         anc[u][i]=anc[anc[u][i-1]][i-1];
 57     for(i=0;i<e[u].size();i++)
 58         if(e[u][i]!=fa)
 59             dfs(e[u][i],u);
 60 }
 61 int lca(int x,int y)
 62 {
 63     int t,i;
 64     if(dep[x]<dep[y]){t=x;x=y;y=t;}
 65     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
 66         if(t&1)    x=anc[x][i];
 67     if(x==y)    return x;
 68     for(i=l2n;i>=0;i--)
 69         if(anc[x][i]!=anc[y][i])
 70         {
 71             x=anc[x][i];
 72             y=anc[y][i];
 73         }
 74     return anc[x][0];
 75 }
 76 }
 77 int an1[210][210];
 78 int d[210][40100];
 79 bool vv[210][40100];
 80 int tt[40100];
 81 bool vis[40100];
 82 int an;
 83 void Change(int x)
 84 {
 85     if(!vis[x])
 86     {//printf("1a%d\n",x);
 87         tt[dd[x]]++;
 88         if(tt[dd[x]]==1)    an++;
 89     }
 90     else
 91     {//printf("1b%d\n",x);
 92         tt[dd[x]]--;
 93         if(tt[dd[x]]==0)    an--;
 94     }
 95     vis[x]^=1;
 96 }
 97 using LCA::lca;
 98 using LCA::anc;
 99 using LCA::dep;
100 #define CLR(x) memset(x,0,sizeof(x))
101 namespace PRE
102 {
103 vector<int> rts[40100];
104 int s;
105 void dfs1(int u,int fa)
106 {
107     int i;
108     tt[dd[u]]++;vis[u]=1;
109     for(i=0;i<rts[u].size();i++)
110     {
111         memcpy(d[rts[u][i]],tt,sizeof(tt));
112         memcpy(vv[rts[u][i]],vis,sizeof(vis));
113     }
114     for(i=0;i<e[u].size();i++)
115         if(e[u][i]!=fa)
116             dfs1(e[u][i],u);
117     tt[dd[u]]--;vis[u]=0;
118 }
119 void dfs2(int u,int fa)
120 {
121     int i;
122     Change(u);
123     int l=lca(rt[s],u);
124     Change(l);
125     for(i=0;i<rts[u].size();i++)
126         an1[s][rts[u][i]]=an;
127     Change(l);
128     for(i=0;i<e[u].size();i++)
129         if(e[u][i]!=fa)
130             dfs2(e[u][i],u);
131     Change(u);
132 }
133 void work()
134 {
135     int i;
136     for(i=1;i<=cnt;i++)    rts[rt[i]].pb(i);
137     dfs1(1,0);
138     for(i=1;i<=cnt;i++)
139     {
140         s=i;
141         dfs2(rt[s],0);
142     }
143 }
144 }
145 int t1[40100];
146 map<int,int> ma;
147 int main()
148 {
149     //freopen("/tmp/2589/3.in","r",stdin);
150     //freopen("/tmp/2589/3.ans","w",stdout);
151     //auto ff=fopen("/tmp/2589/1.in","r");
152     //auto ff=fopen("t1.txt","r");
153     //#define scanf(...) fscanf(ff,__VA_ARGS__)
154     int i,a,b,l,x,y,ra,rb,lans=0;
155     scanf("%d%d",&n,&m);sz=200;//
156     for(i=1;i<=n;i++)    scanf("%d",&dd[i]),t1[++t1[0]]=dd[i];
157     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
158     for(i=1;i<=t1[0];i++)    ma[t1[i]]=i;
159     for(i=1;i<=n;i++)    dd[i]=ma[dd[i]];
160     for(i=1;i<n;i++)
161     {
162         scanf("%d%d",&a,&b);
163         e[a].pb(b);e[b].pb(a);
164     }
165     GBLOCK::work();LCA::dfs(1,0);
166     PRE::work();
167     //#undef scanf
168 /*
169     #undef scanf
170     putchar('a');
171     for(i=1;i<=n;i++)    printf("%d ",bl[i]);
172     puts("");
173     //scanf("%d",new int);
174     puts("b");
175     for(i=1;i<=cnt;i++)
176     {
177         for(int j=1;j<=cnt;j++)
178         {
179             printf("%d ",an1[i][j]);
180         }
181         puts("");
182     }
183     //scanf("%d",new int);
184     putchar('c');
185     for(i=1;i<=cnt;i++)    printf("%d ",rt[i]);
186     puts("");
187     //scanf("%d",new int);
188     putchar('d');
189     for(i=1;i<=n;i++)    printf("%d ",tt[i]);
190     puts("");
191     putchar('e');
192     for(i=1;i<=n;i++)    printf("%d ",vis[i]);
193     puts("");
194     putchar('f');
195     for(i=1;i<=cnt;i++)
196     {
197         for(int j=1;j<=n;j++)
198         {
199             printf("%d$%d ",vv[i][j],d[i][j]);
200         }
201         puts("");
202     }
203 */
204 /*
205 {
206     int x=187,y=rt[bl[187]];
207     if(dep[x]<dep[y])    swap(x,y);
208     while(dep[x]>dep[y])
209     {
210         printf("n%d\n",x);
211         x=anc[x][0];
212     }
213     //assert(x==y);
214 
215     while(x!=y){
216     printf("ttt%d %d %d %d\n",x,y,dep[x],dep[y]);
217     x=anc[x][0];y=anc[y][0];
218     }
219     printf("ttt%d %d %d %d\n",x,y,dep[x],dep[y]);
220 }
221 */
222     for(i=1;i<=m;i++)
223     {
224         scanf("%d%d",&a,&b);a^=lans;
225         if(bl[a]==bl[b])
226         {
227             an=0;
228             x=a;y=b;
229             if(dep[x]<dep[y])    swap(x,y);
230             while(dep[x]>dep[y])
231             {
232                 Change(x);
233                 x=anc[x][0];
234             }
235             while(x!=y)
236             {
237                 Change(x);Change(y);
238                 x=anc[x][0];y=anc[y][0];
239             }
240             Change(x);
241             lans=an;
242             Change(x);
243             //printf("c%d %d\n",a,b);
244             x=a;y=b;
245             if(dep[x]<dep[y])    swap(x,y);
246             while(dep[x]>dep[y])
247             {
248                 Change(x);
249                 x=anc[x][0];
250             }
251             while(x!=y)
252             {
253                 Change(x);Change(y);
254                 x=anc[x][0];y=anc[y][0];
255             }
256         }
257         else
258         {
259             ra=rt[bl[a]];rb=rt[bl[b]];
260             l=lca(ra,rb);
261             #define GD(i) (tt[i]+d[bl[a]][i]+d[bl[b]][i]-2*d[bl[l]][i])//
262             #define GV(i) (vis[i]^vv[bl[a]][i]^vv[bl[b]][i])
263             an=an1[bl[a]][bl[b]];//
264             //
265             x=l;
266             while(x!=rt[bl[l]])
267             {
268                 //printf("d%d\n",x);
269                 tt[dd[x]]-=2;
270                 //if(GD(dd[x])==0)    an--;
271                 //vis[x]^=1;
272                 x=anc[x][0];
273             }
274             //
275             x=a;y=ra;
276             //printf("1s%d\n",GV(5));
277             while(dep[x]>dep[y])
278             {
279                 //printf("tt%d %d %d %d %d %d %d %d\n",x,y,an,GD(dd[x]),tt[dd[x]],d[1][dd[x]],d[2][dd[x]],d[2][dd[x]]);
280                 if(!GV(x))//if(!GV(dd[x]))//
281                 {
282                     tt[dd[x]]++;
283                     if(GD(dd[x])==1)    an++;
284                     //putchar('_');
285                     //printf("$%d$",GD(dd[x]));
286                 }
287                 else
288                 {
289                     tt[dd[x]]--;
290                     if(GD(dd[x])==0)    an--;
291                     //putchar('-');
292                 }
293                 vis[x]^=1;//vis[dd[x]]^=1;
294                 //printf("t%d %d %d %d %d %d %d %d %d\n",ra,rb,l,a,b,bl[a],bl[b],x,an);
295                 x=anc[x][0];
296             }
297             //不需要x!=y的,因为x一定是rt[bl[x]]的子树中节点
298             //assert(x==y);
299             //if(x!=y)    printf("!!%d %d\n",x,y);
300             x=b;y=rb;
301             while(dep[x]>dep[y])
302             {
303                 if(!GV(x))//if(!GV(dd[x]))//
304                 {
305                     tt[dd[x]]++;
306                     if(GD(dd[x])==1)    an++;
307                     //putchar('_');
308                 }
309                 else
310                 {
311                     tt[dd[x]]--;
312                     if(GD(dd[x])==0)    an--;
313                     //putchar('-');
314                 }
315                 vis[x]^=1;//vis[dd[x]]^=1;
316                 //printf("p%d %d %d %d %d %d %d %d %d\n",ra,rb,l,a,b,bl[a],bl[b],x,an);
317                 x=anc[x][0];
318             }
319             x=lca(a,b);
320             //printf("g%d\n",x);
321             if(!GV(x))//if(!GV(dd[x]))//
322             {
323                 tt[dd[x]]++;
324                 if(GD(dd[x])==1)    an++;
325                 //putchar('_');
326             }
327             else
328             {
329                 tt[dd[x]]--;
330                 if(GD(dd[x])==0)    an--;
331                 //putchar('-');
332             }
333             vis[x]^=1;//vis[dd[x]]^=1;
334             lans=an;
335             if(!GV(x))//if(!GV(dd[x]))//
336             {
337                 tt[dd[x]]++;
338             }
339             else
340             {
341                 tt[dd[x]]--;
342             }
343             vis[x]^=1;//vis[dd[x]]^=1;
344             x=a;y=ra;
345             while(dep[x]>dep[y])
346             {
347                 if(!GV(x))//if(!GV(dd[x]))//
348                 {
349                     tt[dd[x]]++;
350                 }
351                 else
352                 {
353                     tt[dd[x]]--;
354                 }
355                 vis[x]^=1;//vis[dd[x]]^=1;
356                 x=anc[x][0];
357             }
358             //assert(x==y);
359             //if(x!=y)    printf("!!%d %d\n",x,y);
360             x=b;y=rb;
361             while(dep[x]>dep[y])
362             {
363                 if(!GV(x))//if(!GV(dd[x]))//
364                 {
365                     tt[dd[x]]++;
366                 }
367                 else
368                 {
369                     tt[dd[x]]--;
370                 }
371                 vis[x]^=1;//vis[dd[x]]^=1;
372                 x=anc[x][0];
373             }
374             //
375             x=l;
376             while(x!=rt[bl[l]])
377             {
378                 tt[dd[x]]+=2;
379                 //vis[x]^=1;
380                 x=anc[x][0];
381             }
382             //
383             #undef G
384         }
385         printf("%d\n",lans);
386         //for(int i=1;i<=n;i++)    assert(tt[i]==0);
387         //for(int i=1;i<=n;i++)    assert(vis[i]==0);
388     }
389     return 0;
390 }

可以发现这种分块方法好像可以搬到括号序上。。。

要能够对于一个k,O(1)求区间内有多少个数,仅出现一次,且“对应数”等于k

并不能直接搬!因为不能前缀和了

。。。并不能研究出来怎么搞(除非多一个log),又一次失败了

失败代码2:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 #include<map>
  6 using namespace std;
  7 #define fi first
  8 #define se second
  9 #define mp make_pair
 10 #define pb push_back
 11 typedef long long ll;
 12 typedef unsigned long long ull;
 13 typedef pair<int,int> pii;
 14 const int N=40;
 15 const int ss=40;
 16 int n,m,a1[N+100];
 17 int t1[N+100];
 18 map<int,int> ma;
 19 vector<int> e[N+100];
 20 namespace LCA
 21 {
 22 int anc[N+100][20],dep[N+100],l2n=19;
 23 void dfs(int u,int fa)
 24 {
 25     int i;
 26     anc[u][0]=fa;
 27     dep[u]=dep[fa]+1;
 28     for(i=1;i<=l2n;i++)
 29         anc[u][i]=anc[anc[u][i-1]][i-1];
 30     for(i=0;i<e[u].size();i++)
 31         if(e[u][i]!=fa)
 32             dfs(e[u][i],u);
 33 }
 34 int lca(int a1,int y)
 35 {
 36     int t,i;
 37     if(dep[a1]<dep[y]){t=a1;a1=y;y=t;}
 38     for(t=dep[a1]-dep[y],i=0;t>0;t>>=1,i++)
 39         if(t&1)    a1=anc[a1][i];
 40     if(a1==y)    return a1;
 41     for(i=l2n;i>=0;i--)
 42         if(anc[a1][i]!=anc[y][i])
 43         {
 44             a1=anc[a1][i];
 45             y=anc[y][i];
 46         }
 47     return anc[a1][0];
 48 }
 49 }
 50 using LCA::lca;
 51 int pl[N+100],dd[2*N+100];
 52 void dfs(int u,int fa)
 53 {
 54     int i;
 55     dd[++dd[0]]=u;pl[u]=dd[0];
 56     for(i=0;i<e[u].size();i++)
 57         if(e[u][i]!=fa)
 58             dfs(e[u][i],u);
 59     dd[++dd[0]]=u;
 60 }
 61 bool vis[N+100];int num[N+100];
 62 int an,sz,sz1;
 63 int bl[2*N+100];
 64 int st[ss+10],ed[ss+10];
 65 int d[ss+10][N+100];//d[i][j]:i块(含)之前j出现次数
 66 bool vv[ss+10][N+100];
 67 int an1[ss+10][ss+10];//an1[i][j]:i块到j块(均含)间答案
 68 void change(int u)
 69 {
 70     if(vis[u])
 71     {
 72         num[a1[u]]--;
 73         if(num[a1[u]]==0)    an--;
 74     }
 75     else
 76     {
 77         if(num[a1[u]]==0)    an++;
 78         num[a1[u]]++;
 79     }
 80     vis[u]^=1;
 81 }
 82 int h1[N+100],tp1;
 83 int main()
 84 {
 85     int i,j,k,x,y,a,b,aa,bb,l,lans=0;
 86     scanf("%d%d",&n,&m);sz=2;
 87     for(i=1;i<=n;i++)    scanf("%d",&a1[i]),t1[++t1[0]]=a1[i];
 88     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
 89     for(i=1;i<=t1[0];i++)    ma[t1[i]]=i;
 90     for(i=1;i<=n;i++)    a1[i]=ma[a1[i]];
 91     for(i=1;i<n;i++)
 92     {
 93         scanf("%d%d",&x,&y);
 94         e[x].pb(y);e[y].pb(x);
 95     }
 96     LCA::dfs(1,0);dfs(1,0);
 97     for(i=1;i<=dd[0];i++)    bl[i]=(i-1)/sz;
 98     sz1=bl[dd[0]];
 99     for(i=0;i<sz1;i++)    st[i]=i*sz+1,ed[i]=(i+1)*sz;
100     st[sz1]=sz1*sz+1;ed[sz1]=dd[0];
101     for(i=0;i<=sz1;i++)
102     {
103         for(j=st[i];j<=ed[i];j++)    change(dd[j]);
104         memcpy(vv[i],vis,sizeof(vis));
105         memcpy(d[i],num,sizeof(num));
106     }
107     memset(num,0,sizeof(num));
108     memset(vis,0,sizeof(vis));
109     an=0;
110     for(i=0;i<=sz1;i++)
111     {
112         for(j=i;j<=sz1;j++)
113         {
114             for(k=st[j];k<=ed[j];k++)    change(dd[k]);
115             an1[i][j]=an;
116         }
117         memset(num,0,sizeof(num));
118         memset(vis,0,sizeof(vis));
119         an=0;
120     }
121     for(i=1;i<=m;i++)
122     {
123         scanf("%d%d",&aa,&bb);
124         a=pl[aa];b=pl[bb];
125         if(bl[a]==bl[b]||bl[a]+1==bl[b])
126         {
127             an=0;
128             for(j=a;j<=b;j++)    change(dd[j]),h1[++tp1]=dd[j];
129             l=lca(aa,bb);
130             if(!vis[aa])    change(aa),h1[++tp1]=aa;
131             if(!vis[bb])    change(bb),h1[++tp1]=bb;
132             if(!vis[l])    change(l),h1[++tp1]=l;
133         }
134         else
135         {
136             #define GV(u) (vis[u]^vv[bl[a]][u]^vv[bl[b]-1][u])
137             #define GN(u) (num[u]+d[bl[b]-1][u]-d[bl[a]][u])
138             #define CG(u) {\
139                 if(GV(u))\
140                 {\
141                     num[a1[u]]--;\
142                     if(GN(a1[u])==0)    an--;\
143                 }\
144                 else\
145                 {\
146                     if(GN(a1[u])==0)    an++;\
147                     num[a1[u]]++;\
148                 }\
149                 h1[++tp1]=u;\
150                 vis[u]^=1;\
151             }
152             an=an1[bl[a]+1][bl[b]-1];
153             for(j=a;j<=ed[bl[a]];j++)    CG(dd[j]);
154             for(j=st[bl[b]];j<=b;j++)    CG(dd[j]);
155             if(!GV(aa))    CG(aa);
156             if(!GV(bb))    CG(bb);
157             l=lca(aa,bb);
158             if(!GV(l))    CG(l);
159         }
160         lans=an;
161         printf("%d\n",lans);
162         for(j=1;j<=tp1;j++)    num[a1[h1[j]]]=vis[h1[j]]=0;
163     }
164     return 0;
165 }

卡常最终版本:

  1 #pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<map>
  7 #include<cmath>
  8 using namespace std;
  9 #define fi first
 10 #define se second
 11 #define mp make_pair
 12 #define pb push_back
 13 typedef long long ll;
 14 typedef unsigned long long ull;
 15 typedef pair<int,int> pii;
 16 int n,sz,m;
 17 vector<int> e[40100];
 18 int rt[40100],cnt,bl[40100];
 19 namespace GBLOCK
 20 {
 21 int st[40100],tp;
 22 void dfs(int u,int fa)
 23 {
 24     int i,ltp=tp;
 25     for(i=0;i<e[u].size();++i)
 26         if(e[u][i]!=fa)
 27         {
 28             dfs(e[u][i],u);
 29             if(tp-ltp>=sz)
 30             {
 31                 rt[++cnt]=u;
 32                 while(tp!=ltp)    bl[st[tp--]]=cnt;
 33             }
 34         }
 35     st[++tp]=u;
 36 }
 37 void work()
 38 {
 39     dfs(1,0);
 40     ++cnt;rt[cnt]=1;
 41     while(tp)    bl[st[tp--]]=cnt;
 42 }
 43 }
 44 int dd[40100];
 45 namespace LCA
 46 {
 47 int anc[40100][20],dep[40100],l2n=19;
 48 void dfs(int u,int fa)
 49 {
 50     int i;
 51     anc[u][0]=fa;
 52     dep[u]=dep[fa]+1;
 53     for(i=1;i<=l2n;++i)
 54         anc[u][i]=anc[anc[u][i-1]][i-1];
 55     for(i=0;i<e[u].size();++i)
 56         if(e[u][i]!=fa)
 57             dfs(e[u][i],u);
 58 }
 59 int lca(int x,int y)
 60 {
 61     int t,i;
 62     if(dep[x]<dep[y]){t=x;x=y;y=t;}
 63     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,++i)
 64         if(t&1)    x=anc[x][i];
 65     if(x==y)    return x;
 66     for(i=l2n;i>=0;--i)
 67         if(anc[x][i]!=anc[y][i])
 68         {
 69             x=anc[x][i];
 70             y=anc[y][i];
 71         }
 72     return anc[x][0];
 73 }
 74 }
 75 int an1[210][210];
 76 int d[210][40100];
 77 bool vv[210][40100];
 78 int tt[40100];
 79 bool vis[40100];
 80 int an;
 81 void Change(int x)
 82 {
 83     if(vis[x])
 84     {
 85         --tt[dd[x]];
 86         if(tt[dd[x]]==0)    --an;
 87     }
 88     else
 89     {
 90         ++tt[dd[x]];
 91         if(tt[dd[x]]==1)    ++an;
 92     }
 93     vis[x]^=1;
 94 }
 95 using LCA::lca;
 96 using LCA::anc;
 97 using LCA::dep;
 98 #define CLR(x) memset(x,0,sizeof(x))
 99 namespace PRE
100 {
101 vector<int> rts[40100];
102 int s;
103 void dfs1(int u,int fa)
104 {
105     int i;
106     ++tt[dd[u]];vis[u]=1;
107     for(i=0;i<rts[u].size();++i)
108     {
109         memcpy(d[rts[u][i]],tt,sizeof(tt));
110         memcpy(vv[rts[u][i]],vis,sizeof(vis));
111     }
112     for(i=0;i<e[u].size();++i)
113         if(e[u][i]!=fa)
114             dfs1(e[u][i],u);
115     --tt[dd[u]];vis[u]=0;
116 }
117 void dfs2(int u,int fa)
118 {
119     int i;
120     Change(u);
121     int l=lca(rt[s],u);
122     Change(l);
123     for(i=0;i<rts[u].size();++i)
124         an1[s][rts[u][i]]=an;
125     Change(l);
126     for(i=0;i<e[u].size();++i)
127         if(e[u][i]!=fa)
128             dfs2(e[u][i],u);
129     Change(u);
130 }
131 void work()
132 {
133     int i;
134     for(i=1;i<=cnt;++i)    rts[rt[i]].pb(i);
135     dfs1(1,0);
136     for(i=1;i<=cnt;++i)
137     {
138         s=i;
139         dfs2(rt[s],0);
140     }
141 }
142 }
143 int t1[40100];
144 map<int,int> ma;
145 int h1[40100],*tp1=h1;
146 inline void read(int &x) {
147     x=0;char ch=getchar();
148     while(ch>'9'||ch<'0')ch=getchar();
149     while(ch>='0'&&ch<='9'){x*=10;x+=(ch-'0');ch=getchar();}
150 }
151 inline void write(int x) {
152     if(x>9) write(x/10);
153     putchar(x%10+'0');
154 }
155 int main()
156 {
157     //freopen("/tmp/2589/2.in","r",stdin);
158     //freopen("/tmp/2589/2.ans","w",stdout);
159     int i,bla,blb,bll,a,b,l,x,y,ra,rb,rl,lans=0,*it;
160     bool *vvbla,*vvblb;int *dbla,*dblb,*dbll;
161     read(n);read(m);sz=300;
162     for(i=1;i<=n;++i)    scanf("%d",&dd[i]),t1[++t1[0]]=dd[i];
163     sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1;
164     for(i=1;i<=t1[0];++i)    ma[t1[i]]=i;
165     for(i=1;i<=n;++i)    dd[i]=ma[dd[i]];
166     for(i=1;i<n;++i)
167     {
168         read(a);read(b);
169         e[a].pb(b);e[b].pb(a);
170     }
171     GBLOCK::work();LCA::dfs(1,0);
172     PRE::work();
173     for(i=1;i<=m;++i)
174     {
175         read(a);read(b);a^=lans;
176         if(bl[a]==bl[b])
177         {
178             an=0;
179             x=a;y=b;
180             if(dep[x]<dep[y])    swap(x,y);
181             while(dep[x]>dep[y])
182             {
183                 Change(x);*(++tp1)=x;
184                 x=anc[x][0];
185             }
186             while(x!=y)
187             {
188                 Change(x);Change(y);*(++tp1)=x;*(++tp1)=y;
189                 x=anc[x][0];y=anc[y][0];
190             }
191             Change(x);*(++tp1)=x;
192             lans=an;
193         }
194         else
195         {
196             bla=bl[a];blb=bl[b];
197             ra=rt[bla];rb=rt[blb];
198             l=lca(ra,rb);bll=bl[l];rl=rt[bll];
199             dbla=d[bla];dblb=d[blb];dbll=d[bll];
200             vvbla=vv[bla];vvblb=vv[blb];
201             #define GD(i) (tt[i]+dbla[i]+dblb[i]-(dbll[i]<<1))
202             #define GV(i) (vis[i]^vvbla[i]^vvblb[i])
203             an=an1[bla][blb];
204             x=l;
205             while(x!=rl)
206             {
207                 tt[dd[x]]-=2;*(++tp1)=x;
208                 x=anc[x][0];
209             }
210             x=a;y=ra;
211             while(x!=y)
212             {
213                 if(GV(x))
214                 {
215                     --tt[dd[x]];
216                     if(GD(dd[x])==0)    --an;
217                 }
218                 else
219                 {
220                     ++tt[dd[x]];
221                     if(GD(dd[x])==1)    ++an;
222                 }
223                 *(++tp1)=x;
224                 vis[x]^=1;
225                 x=anc[x][0];
226             }
227             x=b;y=rb;
228             while(x!=y)
229             {
230                 if(GV(x))
231                 {
232                     --tt[dd[x]];
233                     if(GD(dd[x])==0)    --an;
234                 }
235                 else
236                 {
237                     ++tt[dd[x]];
238                     if(GD(dd[x])==1)    ++an;
239                 }
240                 *(++tp1)=x;
241                 vis[x]^=1;
242                 x=anc[x][0];
243             }
244             x=lca(a,b);
245             if(GV(x))
246             {
247                 --tt[dd[x]];
248                 if(GD(dd[x])==0)    --an;
249             }
250             else
251             {
252                 ++tt[dd[x]];
253                 if(GD(dd[x])==1)    ++an;
254             }
255             *(++tp1)=x;
256             vis[x]^=1;
257             lans=an;
258             #undef G
259         }
260         write(lans);putchar('\n');
261         for(it=h1+1;it<=tp1;++it)    tt[dd[*it]]=vis[*it]=0;
262         tp1=h1;
263     }
264     return 0;
265 }

 

posted @ 2018-08-15 16:17  hehe_54321  阅读(494)  评论(0编辑  收藏  举报
AmazingCounters.com