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 }