• 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
    ",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
    ",siz[tr[x][0]]+1);}
            else {cut(x);read(y);link(x,x+y>n?0:x+y);}
        }
    }
  • 相关阅读:
    一个简单的空间配置器
    【转】c++中placement new操作符
    类的operator new与operator delete的重载【转】
    STL中常用的c++语法
    java编程思想-多态
    java编程思想-复用类(2)
    java编程思想-复用类
    import与require的区别
    gulp插件
    gulp-gulpfile.js语法说明
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/9079518.html
Copyright © 2020-2023  润新知