洛谷P3603 || bzoj 4763 雪辉 && bzoj4812: [Ynoi2017]由乃打扑克
https://www.luogu.org/problemnew/show/P3603
https://www.lydsy.com/JudgeOnline/problem.php?id=4763
就是先树分块,取所有的块顶为关键点
那么任意点与它祖先中离它最近的关键点的距离为根号级别
先预处理出任意两个关键点之间的路径上有的值的bitset
(vv[i][j][k]表示i到j的路径上是否出现值k)
那么,只需要在询问时,对于路径(a,b),得到它路径上有的值的bitset;对于每个询问,把所有得到的bitset或一下就行了
得到bitset的方法见代码。。。
复杂度:n*(sqrt(n)+30000/32)
以下代码常数超大!为了卡常特意手写了bitset,还把块大小改到550(不是根号,实测这样更快...)
1 #pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<bitset> 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,m,F; 16 vector<int> e[100100]; 17 int dd[100100]; 18 const int bsz=480; 19 ull lft[64]; 20 void init() 21 { 22 lft[0]=1; 23 for(int i=1;i<64;i++) lft[i]=lft[i-1]<<1; 24 } 25 struct bs 26 { 27 ull d[bsz]; 28 int _Find_first_zero() 29 { 30 for(int i=0;i<bsz;i++) 31 if(d[i]!=0xffffffffffffffff) 32 return (i<<6)+__builtin_ffsll(~d[i])-1; 33 } 34 void reset() 35 { 36 for(int i=0;i<bsz;i++) d[i]=0; 37 } 38 void set(int p,bool q=1) 39 { 40 if(q) d[p>>6]|=lft[p-((p>>6)<<6)]; 41 else d[p>>6]&=~lft[p-((p>>6)<<6)]; 42 } 43 int count() 44 { 45 int ans=0; 46 for(int i=0;i<bsz;i++) ans+=__builtin_popcountll(d[i]); 47 return ans; 48 } 49 bs &operator|=(const bs &b) 50 { 51 for(int i=0;i<bsz;i++) d[i]|=b.d[i]; 52 return *this; 53 } 54 }; 55 int bl[100100],rt[310],cnt; 56 const int sz=550; 57 namespace GBLOCK 58 { 59 int st[100100],tp; 60 void dfs(int u,int fa) 61 { 62 int i,ltp=tp; 63 for(i=0;i<e[u].size();i++) 64 if(e[u][i]!=fa) 65 { 66 dfs(e[u][i],u); 67 if(tp-ltp>=sz) 68 { 69 rt[++cnt]=u; 70 while(tp!=ltp) bl[st[tp--]]=cnt; 71 } 72 } 73 st[++tp]=u; 74 } 75 void work() 76 { 77 dfs(1,0); 78 ++cnt;rt[cnt]=1; 79 while(tp) bl[st[tp--]]=cnt; 80 } 81 } 82 namespace LCA 83 { 84 int anc[100100][20],dep[100100],l2n=19; 85 void dfs(int u,int fa) 86 { 87 int i; 88 anc[u][0]=fa; 89 dep[u]=dep[fa]+1; 90 for(i=1;i<=l2n;i++) 91 anc[u][i]=anc[anc[u][i-1]][i-1]; 92 for(i=0;i<e[u].size();i++) 93 if(e[u][i]!=fa) 94 dfs(e[u][i],u); 95 } 96 int lca(int x,int y) 97 { 98 int t,i; 99 if(dep[x]<dep[y]){t=x;x=y;y=t;} 100 for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++) 101 if(t&1) x=anc[x][i]; 102 if(x==y) return x; 103 for(i=l2n;i>=0;i--) 104 if(anc[x][i]!=anc[y][i]) 105 { 106 x=anc[x][i]; 107 y=anc[y][i]; 108 } 109 return anc[x][0]; 110 } 111 } 112 using LCA::lca; 113 using LCA::dep; 114 using LCA::anc; 115 int nn[100100],nnn; 116 bs vv[310][310];//vv[i][j]:rt[i],rt[j]间答案 117 int num[30100];bs vis; 118 namespace PRE 119 { 120 int s; 121 void dfs(int u,int fa) 122 { 123 int i; 124 if(!num[dd[u]]) vis.set(dd[u]); 125 ++num[dd[u]]; 126 if(nn[u]) vv[s][nn[u]]=vis; 127 for(i=0;i<e[u].size();i++) 128 if(e[u][i]!=fa) 129 dfs(e[u][i],u); 130 --num[dd[u]]; 131 if(!num[dd[u]]) vis.set(dd[u],0); 132 } 133 void work() 134 { 135 int i; 136 for(i=1;i<=cnt;i++) 137 if(!nn[rt[i]]) 138 nn[rt[i]]=++nnn; 139 for(i=1;i<=n;i++) 140 if(nn[i]) 141 { 142 s=nn[i]; 143 dfs(i,0); 144 } 145 } 146 } 147 bs tt; 148 void jump1(int &x,int ed) 149 { 150 if(ed==-1) ed=rt[bl[x]]; 151 while(x!=ed) 152 { 153 tt.set(dd[x]); 154 x=anc[x][0]; 155 } 156 tt.set(dd[x]); 157 } 158 void jump2(int &x,int ed) 159 { 160 int x1=x; 161 while(x1!=1&&dep[rt[bl[x1]]]>=dep[ed]) x1=rt[bl[x1]]; 162 tt|=vv[nn[x]][nn[x1]]; 163 x=x1; 164 } 165 int main() 166 { 167 168 init(); 169 int i,a,b,a1,a2,t,lans=0,l; 170 scanf("%d%d%d",&n,&m,&F); 171 for(i=1;i<=n;i++) scanf("%d",&dd[i]); 172 for(i=1;i<n;i++) 173 { 174 scanf("%d%d",&a,&b); 175 e[a].pb(b);e[b].pb(a); 176 } 177 GBLOCK::work();LCA::dfs(1,0);PRE::work(); 178 while(m--) 179 { 180 scanf("%d",&t);tt.reset(); 181 for(i=1;i<=t;i++) 182 { 183 scanf("%d%d",&a,&b); 184 if(F) a^=lans,b^=lans; 185 l=lca(a,b); 186 if(a!=1&&dep[rt[bl[a]]]>=dep[l]) jump1(a,-1); 187 if(b!=1&&dep[rt[bl[b]]]>=dep[l]) jump1(b,-1); 188 jump2(a,l); 189 jump2(b,l); 190 jump1(a,l);jump1(b,l); 191 } 192 a1=tt.count(); 193 a2=tt._Find_first_zero(); 194 printf("%d %d\n",a1,a2); 195 lans=a1+a2; 196 } 197 return 0; 198 }
此方法相比直接分块然后处理边角,常数还是算小的,能够比bzoj2589https://www.cnblogs.com/hehe54321/p/9463519.html里面的做法快,但是还是过不去...
失败代码:
1 #pragma GCC optimize(3) 2 //#pragma GCC target("sse3","sse2","sse") 3 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector") 4 #pragma GCC diagnostic error "-fwhole-program" 5 #pragma GCC diagnostic error "-fcse-skip-blocks" 6 #pragma GCC diagnostic error "-funsafe-loop-optimizations" 7 #include<cstdio> 8 #include<algorithm> 9 #include<cstring> 10 #include<vector> 11 #include<map> 12 using namespace std; 13 #define fi first 14 #define se second 15 #define mp make_pair 16 #define pb push_back 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef unsigned ul; 20 typedef pair<int,int> pii; 21 char B[1<<23],*SS=B; 22 #define getchar() (*SS++) 23 template<typename T> 24 inline void read(T &x) 25 { 26 x=0;int f=1;char ch=getchar(); 27 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 28 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 29 x*=f; 30 } 31 int n,m; 32 struct E 33 { 34 int to,nxt; 35 }e[80100]; 36 int f1[40100],ne; 37 int dd[40100]; 38 int r[40100]; 39 const int bsz=1250; 40 ul lft[32]; 41 void init() 42 { 43 lft[0]=1; 44 for(int i=1;i<32;i++) lft[i]=lft[i-1]<<1; 45 } 46 struct bs 47 { 48 ul d[bsz]; 49 void reset(){memset(d,0,sizeof(d));} 50 void set(int p,bool q=1) 51 { 52 if(q) d[p>>5]|=lft[p&31]; 53 else d[p>>5]&=~lft[p&31]; 54 } 55 int count() 56 { 57 int ans=0; 58 for(int i=0;i<bsz;i++) ans+=__builtin_popcount(d[i]); 59 return ans; 60 } 61 bs &operator|=(const bs &b) 62 { 63 for(int i=0;i<bsz;i++) d[i]|=b.d[i]; 64 return *this; 65 } 66 }; 67 int bl[40100],rt[402],cnt; 68 const int sz=100; 69 namespace GBLOCK 70 { 71 int st[40100],tp; 72 void dfs(int u,int fa) 73 { 74 int i,ltp=tp; 75 for(i=f1[u];i;i=e[i].nxt) 76 if(e[i].to!=fa) 77 { 78 dfs(e[i].to,u); 79 if(tp-ltp>=sz) 80 { 81 rt[++cnt]=u; 82 while(tp!=ltp) bl[st[tp--]]=cnt; 83 } 84 } 85 st[++tp]=u; 86 } 87 void work() 88 { 89 dfs(1,0); 90 ++cnt;rt[cnt]=1; 91 while(tp) bl[st[tp--]]=cnt; 92 } 93 } 94 namespace LCA 95 { 96 int anc[40100][17],dep[40100],l2n=16; 97 void dfs(int u,int fa) 98 { 99 int i; 100 anc[u][0]=fa; 101 dep[u]=dep[fa]+1; 102 for(i=1;i<=l2n;i++) 103 anc[u][i]=anc[anc[u][i-1]][i-1]; 104 for(i=f1[u];i;i=e[i].nxt) 105 if(e[i].to!=fa) 106 dfs(e[i].to,u); 107 } 108 int lca(int x,int y) 109 { 110 int t,i; 111 if(dep[x]<dep[y]){t=x;x=y;y=t;} 112 for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++) 113 if(t&1) x=anc[x][i]; 114 if(x==y) return x; 115 for(i=l2n;i>=0;i--) 116 if(anc[x][i]!=anc[y][i]) 117 { 118 x=anc[x][i]; 119 y=anc[y][i]; 120 } 121 return anc[x][0]; 122 } 123 } 124 using LCA::lca; 125 using LCA::dep; 126 using LCA::anc; 127 int nn[40100],nnn,nn1[402]; 128 bs vvv[80002];int mem; 129 int vv[402][402];//vv[i][j]:rt[i],rt[j]间答案 130 bs vis; 131 namespace TTT 132 { 133 int anr[402][10],l2n=9; 134 int dnn1[402]; 135 void work() 136 { 137 int i,j; 138 for(i=1;i<=nnn;i++) anr[i][0]=nn[r[nn1[i]]]; 139 //puts("anr"); 140 //for(i=1;i<=nnn;i++) printf("%d ",anr[i][0]); 141 //puts(""); 142 //return; 143 for(j=1;j<=l2n;j++) 144 for(i=1;i<=nnn;i++) 145 anr[i][j]=anr[anr[i][j-1]][j-1]; 146 for(i=1;i<=nnn;i++) dnn1[i]=dep[nn1[i]]; 147 } 148 } 149 using TTT::anr; 150 using TTT::dnn1; 151 namespace PRE 152 { 153 void work() 154 { 155 int i,j; 156 for(i=1;i<=cnt;i++) 157 if(!nn[rt[i]]) 158 nn[rt[i]]=++nnn,nn1[nnn]=rt[i]; 159 for(i=1;i<=n;i++) 160 if(nn[i]) 161 { 162 vis.reset(); 163 j=i; 164 vis.set(dd[j]); 165 while(j!=1) 166 { 167 j=anc[j][0]; 168 vis.set(dd[j]); 169 if(nn[j]) vvv[vv[nn[i]][nn[j]]=++mem]=vis; 170 } 171 } 172 } 173 } 174 bs tt; 175 void jump1(int &x,int ed) 176 { 177 if(ed==-1) ed=r[x]; 178 while(x!=ed) 179 { 180 tt.set(dd[x]); 181 x=anc[x][0]; 182 } 183 tt.set(dd[x]); 184 } 185 void jump2(int &x,int ed) 186 { 187 int i,x1=nn[x]; 188 if(!x1) return; 189 //while(x1!=1&&dep[r[x1]]>=dep[ed]) x1=r[x1]; 190 for(i=TTT::l2n;i>=0;i--) 191 if(dnn1[anr[x1][i]]>=dep[ed]) 192 x1=anr[x1][i]; 193 x1=nn1[x1]; 194 tt|=vvv[vv[nn[x]][nn[x1]]]; 195 x=x1; 196 } 197 int t1[40100]; 198 map<int,int> ma; 199 int main() 200 { 201 //freopen("/tmp/2589/3.in","r",stdin); 202 //freopen("/tmp/2589/3.ans","w",stdout); 203 fread(B,1,1<<23,stdin); 204 init(); 205 int i,a,b,lans=0,l; 206 read(n);read(m); 207 for(i=1;i<=n;i++) read(dd[i]),t1[++t1[0]]=dd[i]; 208 sort(t1+1,t1+t1[0]+1);t1[0]=unique(t1+1,t1+t1[0]+1)-t1-1; 209 for(i=1;i<=t1[0];i++) ma[t1[i]]=i; 210 for(i=1;i<=n;i++) dd[i]=ma[dd[i]]; 211 for(i=1;i<n;i++) 212 { 213 read(a);read(b); 214 e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne; 215 e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne; 216 } 217 GBLOCK::work();LCA::dfs(1,0);PRE::work(); 218 for(i=1;i<=n;i++) r[i]=rt[bl[i]]; 219 TTT::work(); 220 while(m--) 221 { 222 tt.reset(); 223 read(a);read(b); 224 a^=lans; 225 l=lca(a,b); 226 if(dep[r[a]]>=dep[l]) jump1(a,-1); 227 if(dep[r[b]]>=dep[l]) jump1(b,-1); 228 jump2(a,l); 229 jump2(b,l); 230 jump1(a,l);jump1(b,l); 231 lans=tt.count(); 232 printf("%d\n",lans); 233 } 234 return 0; 235 }
https://www.lydsy.com/JudgeOnline/problem.php?id=4812
此题也是一样的做法,得到一个bitset,之后统计答案
统计答案的话,对于bitset内每一个数字,拆成一些0~0xffff之间的数处理(因为这样就可以预处理了)
统计答案具体方法不写了。。。
注意:如果直接上面那个改改,是过不去的...常数太大
有效卡常:
1.把预处理任意两个关键点之间信息改为只预处理每个关键点到它祖先中所有关键点的信息
2.vector改邻接表
1 #pragma GCC optimize(3) 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<bitset> 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 unsigned ul; 15 typedef pair<int,int> pii; 16 char B[1<<26],*SSS=B; 17 #define getchar() (*SSS++) 18 int n,m; 19 struct E 20 { 21 int to,nxt; 22 }e[200100]; 23 int f1[100100],ne; 24 int dd[100100]; 25 const int bsz=938; 26 ul lft[32]; 27 ul pw[30100][31]; 28 int low[70000],high[70000];ul an[70000][31]; 29 template<typename T> 30 inline void read(T &x) 31 { 32 x=0;int f=1;char ch=getchar(); 33 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 34 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 35 x*=f; 36 } 37 void init() 38 { 39 int j,nt,k; 40 lft[0]=1; 41 for(int i=1;i<32;i++) lft[i]=lft[i-1]<<1; 42 for(ul i=1;i<=30010;i++) 43 { 44 pw[i][0]=1; 45 for(j=1;j<=30;j++) pw[i][j]=pw[i][j-1]*i; 46 } 47 for(ul i=1,t;i<65536;i++) 48 { 49 nt=0; 50 t=i; 51 for(j=0;j<16;j++) 52 { 53 if(i&lft[j]) low[i]++,t^=lft[j]; 54 else break; 55 } 56 for(j=15;j>=0;j--) 57 { 58 if(i&lft[j]) high[i]++,t^=lft[j]; 59 else break; 60 } 61 if(i!=65535) 62 { 63 for(j=0;j<16;j++) 64 { 65 if(t&lft[j]) nt++; 66 else 67 { 68 for(k=0;k<=30;k++) 69 { 70 an[i][k]+=pw[nt][k]; 71 } 72 nt=0; 73 } 74 } 75 for(k=0;k<=30;k++) 76 { 77 an[i][k]+=pw[nt][k]; 78 } 79 nt=0; 80 } 81 } 82 } 83 struct bs 84 { 85 ul d[bsz]; 86 void reset() 87 { 88 memset(d,0,sizeof(d)); 89 } 90 void set(int p,bool q=1) 91 { 92 if(q) d[p>>5]|=lft[p&31]; 93 else d[p>>5]&=~lft[p&31]; 94 } 95 bs &operator|=(const bs &b) 96 { 97 for(int i=0;i<bsz;i++) d[i]|=b.d[i]; 98 return *this; 99 } 100 ul calc(int k) 101 { 102 ul ans=0,l=0;ul t; 103 #define CAL(t) \ 104 {\ 105 if(t==0xffff) l+=16;\ 106 else\ 107 {\ 108 l+=low[t];ans+=pw[l][k];\ 109 ans+=an[t][k];\ 110 l=high[t];\ 111 }\ 112 } 113 for(int i=0;i<bsz;i++) 114 { 115 t=d[i]&0xffff;CAL(t); 116 t=(d[i]>>16);CAL(t); 117 } 118 return ans+=pw[l][k]; 119 } 120 }; 121 int bl[100100],rt[202],cnt; 122 const int sz=500; 123 namespace GBLOCK 124 { 125 int st[100100],tp; 126 void dfs(int u,int fa) 127 { 128 int k,ltp=tp; 129 for(k=f1[u];k;k=e[k].nxt) 130 if(e[k].to!=fa) 131 { 132 dfs(e[k].to,u); 133 if(tp-ltp>=sz) 134 { 135 rt[++cnt]=u; 136 while(tp!=ltp) bl[st[tp--]]=cnt; 137 } 138 } 139 st[++tp]=u; 140 } 141 void work() 142 { 143 dfs(1,0); 144 ++cnt;rt[cnt]=1; 145 while(tp) bl[st[tp--]]=cnt; 146 } 147 } 148 namespace LCA 149 { 150 int anc[100100][18],dep[100100],l2n=17; 151 void dfs(int u,int fa) 152 { 153 int k; 154 anc[u][0]=fa; 155 dep[u]=dep[fa]+1; 156 for(k=1;k<=l2n;k++) 157 anc[u][k]=anc[anc[u][k-1]][k-1]; 158 for(k=f1[u];k;k=e[k].nxt) 159 if(e[k].to!=fa) 160 dfs(e[k].to,u); 161 } 162 int lca(int x,int y) 163 { 164 int t,i; 165 if(dep[x]<dep[y]){t=x;x=y;y=t;} 166 for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++) 167 if(t&1) x=anc[x][i]; 168 if(x==y) return x; 169 for(i=l2n;i>=0;i--) 170 if(anc[x][i]!=anc[y][i]) 171 { 172 x=anc[x][i]; 173 y=anc[y][i]; 174 } 175 return anc[x][0]; 176 } 177 } 178 using LCA::lca; 179 using LCA::dep; 180 using LCA::anc; 181 int nn[100100],nnn; 182 bs vv[202][202];//vv[i][j]:rt[i],rt[j]间答案 183 int num[30100];bs vis; 184 namespace PRE 185 { 186 void work() 187 { 188 int i,j; 189 for(i=1;i<=cnt;i++) 190 if(!nn[rt[i]]) 191 nn[rt[i]]=++nnn; 192 for(i=1;i<=n;i++) 193 if(nn[i]) 194 { 195 vis.reset(); 196 j=i;vis.set(dd[j]); 197 vv[nn[i]][nn[i]]=vis; 198 while(j!=1) 199 { 200 j=anc[j][0]; 201 vis.set(dd[j]); 202 if(nn[j]) vv[nn[i]][nn[j]]=vis; 203 } 204 } 205 } 206 } 207 bs tt; 208 void jump1(int &x,int ed) 209 { 210 if(ed==-1) ed=rt[bl[x]]; 211 while(x!=ed) 212 { 213 tt.set(dd[x]); 214 x=anc[x][0]; 215 } 216 tt.set(dd[x]); 217 } 218 void jump2(int &x,int ed) 219 { 220 int x1=x; 221 while(x1!=1&&dep[rt[bl[x1]]]>=dep[ed]) x1=rt[bl[x1]]; 222 tt|=vv[nn[x]][nn[x1]]; 223 x=x1; 224 } 225 int main() 226 { 227 //freopen("/tmp/4812/1.in","r",stdin); 228 //freopen("/tmp/4812/1.ans","w",stdout); 229 fread(B,1,1<<26,stdin); 230 init(); 231 int i,a,b,t,l;ul a1,b1;ul lans=0; 232 read(n);read(m); 233 for(i=1;i<=n;i++) read(dd[i]); 234 for(i=1;i<n;i++) 235 { 236 read(a);read(b); 237 e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne; 238 e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne; 239 } 240 GBLOCK::work();LCA::dfs(1,0);PRE::work(); 241 while(m--) 242 { 243 read(t);tt.reset(); 244 for(i=1;i<=t;i++) 245 { 246 read(a1);read(b1); 247 a=a1^lans;b=b1^lans; 248 l=lca(a,b); 249 if(a!=1&&dep[rt[bl[a]]]>=dep[l]) jump1(a,-1); 250 if(b!=1&&dep[rt[bl[b]]]>=dep[l]) jump1(b,-1); 251 jump2(a,l); 252 jump2(b,l); 253 jump1(a,l);jump1(b,l); 254 } 255 read(t); 256 lans=tt.calc(t); 257 printf("%u\n",lans); 258 } 259 return 0; 260 }