bzoj2002
非常好的一篇博客(LCT)
时间效率相差不大
1.分块
#include<cstdio> #include<cmath> #include<cctype> using namespace std; const int maxn=200004; int n,cnt,num,whic[maxn],a[maxn],l[510],r[510],muc[maxn],nex[maxn]; inline int read(){ char ch=getchar();int k=0; while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)){k=(k<<1)+(k<<3)+ch-'0';ch=getchar();} return k; } int query(int x){ int t=0;for(;x;t+=muc[x],x=nex[x]);return t; } int main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); num=sqrt(n); if(n%num)cnt=n/num+1;else cnt=n/num; for(int i=1,j=num;i<=cnt;i++,j+=num) {l[i]=r[i-1]+1;r[i]=j;}r[cnt]=n; for(int i=1;i<=n;i++) whic[i]=(i-1)/num+1; for(int i=n;i>=1;i--){ if(i+a[i]>n) muc[i]=1; else if(whic[i]==whic[i+a[i]]) {muc[i]=muc[i+a[i]]+1;nex[i]=nex[i+a[i]];} else muc[i]=1,nex[i]=i+a[i]; } int m=read(); while(m--){ int flag=read(),x=read()+1; if(flag==1) printf("%d\n",query(x)); else{ int y=read();a[x]=y; for(int i=x;i>=l[whic[x]];i--){ if(whic[i]==whic[i+a[i]]) muc[i]=muc[i+a[i]]+1,nex[i]=nex[i+a[i]]; else muc[i]=1,nex[i]=i+a[i]; } } } return 0; }
2.LCT
思路概要:把该点连向跳到的点,并保证跳到的点深度比他小,则最后左儿子的siz+1即答案
#include<cstdio> #include<cctype> #include<algorithm> #define ls tr[x][0] #define rs tr[x][1] #define maxn 300100 using namespace std; int n,f[maxn],siz[maxn],tr[maxn][2],rev[maxn],tmp[maxn]; inline void pushup(int x){siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+1;} inline void pushr(int x){if(rev[x])swap(ls,rs);rev[x]^=1;} inline void pushdown(int x){if(rev[x]){if(ls)pushr(ls);if(rs)pushr(rs);rev[x]=0;}} inline bool isroot(int x){return (tr[f[x]][0]==x||tr[f[x]][1]==x);} inline void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } inline void rotate(int x){ int fa=f[x],gfa=f[fa],whicx=tr[fa][1]==x,flag=isroot(fa); tr[fa][whicx]=tr[x][whicx^1];f[tr[fa][whicx]]=fa; tr[x][whicx^1]=fa;f[fa]=x; f[x]=gfa;if(flag)tr[gfa][tr[gfa][1]==fa]=x; pushup(fa); } inline void splay(int x){ int y=x,siz=0,z; tmp[++siz]=y; while(isroot(y))tmp[++siz]=y=f[y]; while(siz)pushdown(tmp[siz--]); while(isroot(x)){ y=f[x];z=f[y]; if(isroot(y))rotate((tr[y][1]==x)==(tr[z][1]==y)?y:x); if(isroot(x))rotate(x); } pushup(x); } inline void access(int x){for(int y=0;x;x=f[y=x])splay(x),rs=y,pushup(x);} inline void makeroot(int x){access(x);splay(x);pushr(x);} inline int findroot(int x){ access(x);splay(x);pushdown(x); while(ls)x=ls,pushdown(x); return x; } inline void cut(int x){access(x);splay(x);tr[x][0]=f[tr[x][0]]=0;} inline void link(int x,int y){makeroot(x);f[x]=y;} int main(){ read(n);int k; for(int i=1;i<=n;i++)read(k),f[i]=i+k>n?0:i+k,siz[i]=1; int m,typ,x,y;read(m); while(m--){ read(typ);read(x);x++; if(typ==1){access(x);splay(x);printf("%d\n",siz[tr[x][0]]+1);} else {cut(x);read(y);link(x,x+y>n?0:x+y);} } }