[bzoj4763]雪辉&[bzoj4812][Ynoi2017]由乃打扑克
来自FallDream的博客,未经允许,请勿转载,谢谢。
cut掉部分题面。
给一个n个点的树,点有点权,有m次询问,每次询问多条链的并有多少种不同的点权以及它的mex
mex就是一个集合中最小的没有出现的非负整数,注意0要算
比如说集合是1,9,2,6,0,8,1,7,则出现了0,1,2,6,7,8,9这7种不同的点权,因为没有3所以mex是3
n<=100000,总共询问的链数量<=100000 权值<=30000
考虑对树分块,预处理每个块的中心到它父亲中同样是中心的点的bitset,然后查询的时候先暴力跳到中心,再能跳到上一个中心就跳,最后再暴力跳即可。
手写bitset来查询答案。
预处理复杂度$n\sqrt{n}$,每次询问复杂度是$O(\sqrt{n}+\frac{30000}{64})$
另一道由乃打扑克也是同样的做法,最后询问的时候,16位可以一起处理,预处理0-65535里面每个数低位连续的1的数量,中间的1在不同幂次下的贡献和高位连续的1的数量。
雪辉
#include<iostream> #include<cstdio> #define MN 100000 #define MB 320 #define MD 17 #define ull unsigned long long #define getchar() (*S++) char B[1<<26],*S=B; using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,m,flag,w[MN+5],head[MN+5],cnt=0,fa[MD+5][MN+5],mx[MN+5]; int mark[MN+5],dep[MN+5],rt[MB+5],rtnum=0,top[MN+5],Num[MN+5]; struct edge{int to,next;}e[MN*2+5]; ull MAXN=0; struct Bitset { ull s[470];int len; void Clear(){for(int i=0;i<470;++i) s[i]=0;len=0;} void operator |=(int x){s[x>>6]|=1LL<<(x&63);len=max(len,x>>6);} void operator |=(const Bitset&y) { len=max(len,y.len); for(int i=0;i<=len;++i) s[i]|=y.s[i]; } int num() { int res=0; for(int i=0;i<=len;++i) res+=Num[s[i]>>48]+Num[(s[i]>>32)&65535]+Num[(s[i]>>16)&65535]+Num[s[i]&65535]; return res; } int Query() { for(int i=0;i<470;++i) if(s[i]!=MAXN) for(int j=0;j<64;++j) if(!(s[i]&((ull)1<<j))) return i*64+j; } }b[MB+5][MB+5],ans; inline void ins(int f,int t) { e[++cnt]=(edge){t,head[f]};head[f]=cnt; e[++cnt]=(edge){f,head[t]};head[t]=cnt; } void init(int x) { mx[x]=dep[x]; for(int i=head[x];i;i=e[i].next) if(e[i].to!=fa[0][x]) { fa[0][e[i].to]=x; dep[e[i].to]=dep[x]+1; init(e[i].to); mx[x]=max(mx[x],mx[e[i].to]); } if(mx[x]-dep[x]>=MB||x==1) mx[x]=0,rt[mark[x]=++rtnum]=x; } inline int lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j) if(k&1) x=fa[j][x]; if(x==y) return x; for(int i=MD;~i;--i) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y]; return fa[0][x]; } int last=0; int main() { fread(B,1,1<<26,stdin); n=read();m=read();flag=read(); for(int i=0;i<64;++i) MAXN|=(ull)1<<i; for(int i=0;i<=65536;++i) for(int j=i;j;j>>=1) Num[i]+=(j&1); for(int i=1;i<=n;++i) w[i]=read(); for(int i=1;i<n;++i) ins(read(),read()); dep[1]=1;init(1); for(int i=1;i<=MD;++i) for(int j=1;j<=n;++j) fa[i][j]=fa[i-1][fa[i-1][j]]; for(int i=1;i<=rtnum;++i) { Bitset now;now.Clear();now|=w[rt[i]];b[i][i]=now; for(int k=fa[0][rt[i]];k;k=fa[0][k]) { now|=w[k]; if(mark[k]) { b[i][mark[k]]=now; if(!top[rt[i]]) top[rt[i]]=k; } } } for(int i=1;i<=m;++i) { ans.Clear();int nn=read(); for(int j=1;j<=nn;++j) { int x=read(),y=read(),xx,yy; if(flag) x^=last,y^=last; int z=lca(x,y);ans|=w[x];ans|=w[y]; for(;!mark[x]&&dep[x]>dep[z];) x=fa[0][x],ans|=w[x]; for(;!mark[y]&&dep[y]>dep[z];) y=fa[0][y],ans|=w[y]; for(xx=x;dep[top[xx]]>=dep[z];xx=top[xx]); for(yy=y;dep[top[yy]]>=dep[z];yy=top[yy]); ans|=b[mark[x]][mark[xx]]; ans|=b[mark[y]][mark[yy]]; for(;xx!=yy;) { if(dep[xx]<dep[yy]) swap(xx,yy); xx=fa[0][xx];ans|=w[xx]; } } int x=ans.num(),y=ans.Query(); last=x+y; printf("%d %d\n",x,y); } return 0; }
由乃打扑克
#include<iostream> #include<cstdio> #define MN 100000 #define MB 350 #define MD 17 #define int unsigned int #define uint int #define ull unsigned long long #define getchar() (*S++) char B[1<<26],*S=B; using namespace std; inline long long read() { long long x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int n,m,w[MN+5],head[MN+5],cnt=0,fa[MD+5][MN+5],mx[MN+5]; int mark[MN+5],dep[MN+5],rt[MB+5],rtnum=0,top[MN+5],front[MN+5],back[MN+5]; uint pw[30005][32],Num[65536][32],K,last=0; struct edge{int to,next;}e[MN*2+5]; void Combine(uint&ans,uint&len,int x) { if(x==65535) {len+=16;return;} len+=front[x];ans+=pw[len][K]; ans+=Num[x][K];len=back[x]; } struct Bitset { ull s[470];int len; void Clear(){for(int i=0;i<470;++i) s[i]=0;len=0;} void operator |=(int x){s[x>>6]|=1LL<<(x&63);len=max(len,x>>6);} void operator |=(const Bitset&y) { len=max(len,y.len); for(int i=0;i<=len;++i) s[i]|=y.s[i]; } uint Query(int k) { uint ans=0,L=0; for(int i=0;i<=len;++i) Combine(ans,L,s[i]&65535), Combine(ans,L,(s[i]>>16)&65535), Combine(ans,L,(s[i]>>32)&65535), Combine(ans,L,(s[i]>>48)&65535); return (ans+=pw[L][k]); } }b[MB+5][MB+5],ans; inline void ins(int f,int t) { e[++cnt]=(edge){t,head[f]};head[f]=cnt; e[++cnt]=(edge){f,head[t]};head[t]=cnt; } void init(int x) { mx[x]=dep[x]; for(int i=head[x];i;i=e[i].next) if(e[i].to!=fa[0][x]) { fa[0][e[i].to]=x; dep[e[i].to]=dep[x]+1; init(e[i].to); mx[x]=max(mx[x],mx[e[i].to]); } if(mx[x]-dep[x]>=MB||x==1) mx[x]=0,rt[mark[x]=++rtnum]=x; } inline int lca(int x,int y) { if(dep[x]<dep[y]) swap(x,y); for(int k=dep[x]-dep[y],j=0;k;k>>=1,++j) if(k&1) x=fa[j][x]; if(x==y) return x; for(int i=MD;~i;--i) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y]; return fa[0][x]; } main() { fread(B,1,1<<26,stdin); n=read();m=read(); for(int i=1;i<=30000;++i) { int k=1;pw[i][0]=1; for(int j=1;j<=30;++j) pw[i][j]=(k*=i); } for(int i=0;i<=65534;++i) { int j=0,flag=0; for(int k=i,kk=1;kk<=16;++kk,k>>=1) if(k&1) ++j; else { if(!flag) flag=1,front[i]=j; else for(int kkk=0;kkk<=30;++kkk) Num[i][kkk]+=pw[j][kkk]; j=0; } back[i]=j; } for(int i=1;i<=n;++i) w[i]=read(); for(int i=1;i<n;++i) ins(read(),read()); dep[1]=1;init(1); for(int i=1;i<=MD;++i) for(int j=1;j<=n;++j) fa[i][j]=fa[i-1][fa[i-1][j]]; for(int i=1;i<=rtnum;++i) { Bitset now;now.Clear();now|=w[rt[i]];b[i][i]=now; for(int k=fa[0][rt[i]];k;k=fa[0][k]) { now|=w[k]; if(mark[k]) { b[i][mark[k]]=now; if(!top[rt[i]]) top[rt[i]]=k; } } } for(int i=1;i<=m;++i) { ans.Clear();int nn=read(); for(int j=1;j<=nn;++j) { uint x=(read()^last),y=(read()^last),xx,yy; uint z=lca(x,y);ans|=w[x];ans|=w[y]; if(x<1||x>n||y<1||y>n) return 0; for(;!mark[x]&&dep[x]>dep[z];) x=fa[0][x],ans|=w[x]; for(;!mark[y]&&dep[y]>dep[z];) y=fa[0][y],ans|=w[y]; for(xx=x;dep[top[xx]]>=dep[z];xx=top[xx]); for(yy=y;dep[top[yy]]>=dep[z];yy=top[yy]); ans|=b[mark[x]][mark[xx]]; ans|=b[mark[y]][mark[yy]]; for(;xx!=yy;) { if(dep[xx]<dep[yy]) swap(xx,yy); xx=fa[0][xx];ans|=w[xx]; } } printf("%u\n",last=ans.Query(K=read())); } return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream