• [bzoj3600]没有人的算术


    来自FallDream的博客,未经允许,请勿转载,谢谢。




    考虑用一个实数来表示大小关系。维护两个平衡树,一棵splay来维护区间,然后一个替罪羊来维护每个数的标号。

    插入一种数的时候,可以取它的前驱后继的平均值。然后替罪羊重建的时候正好吧数字重新标号即可。

    #include<iostream>
    #include<cstdio>
    #define MN 500000
    #define ld long double
    #define INF (ld)1e99
    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;
    }
    
    namespace SGT
    {
        ld s[MN+5];int A[MN+5],B[MN+5],rt,fa[MN+5],cnt=0,c[MN+5][2],mark=0,q[MN+5],size[MN+5],top;
        int GetID(int&x,int a,int b,ld lt,ld rt,int last=0)
        {
            if(!x){
                x=++cnt;A[x]=a;B[x]=b;
                s[x]=(lt+rt)/2.0;fa[x]=last;size[x]=1;
                return cnt;
            }
            if(x!=2&&A[x]==a&&B[x]==b) return x;
            int res;
            if(x==2||((s[A[x]]==s[a]&&s[B[x]]<s[b])||s[A[x]]<s[a])) res=GetID(c[x][1],a,b,s[x],rt,x);
            else res=GetID(c[x][0],a,b,lt,s[x],x);
            size[x]=size[c[x][0]]+size[c[x][1]]+1;
            if(max(size[c[x][0]],size[c[x][1]])>0.75*size[x]) mark=x;
            return res;
        }    
        void ins(int&x,int a,int b,ld ci,int last=0)
        {
            if(!x){
                x=++cnt;s[x]=ci;
                A[x]=a;B[x]=b;fa[x]=last;
                return;
            }    
            if((s[A[x]]==s[a]&&s[B[x]]<s[b])||s[A[x]]<s[a]) ins(c[x][1],a,b,ci,x);
            else ins(c[x][0],a,b,ci,x);
            size[x]=size[c[x][0]]+size[c[x][1]]+1;
        }
        void Dfs(int x)
        {
            if(c[x][0]) Dfs(c[x][0]);
            q[++top]=x;
            if(c[x][1]) Dfs(c[x][1]);
        }
        void build(int&x,int l,int r,ld lt,ld rt,int last)
        {
            if(l>r){x=0;return;}
            int mid=l+r>>1;x=q[mid];s[x]=(lt+rt)/2.0;fa[x]=last;
            build(c[x][0],l,mid-1,lt,s[x],x);
            build(c[x][1],mid+1,r,s[x],rt,x);
            size[x]=size[c[x][0]]+size[c[x][1]]+1;
        }
        void rebuild()
        {
            top=0;Dfs(mark);int y=fa[mark];
            if(!y) build(rt,1,top,s[q[1]],s[q[top]],0);
            else build(c[y][c[y][1]==mark],1,top,s[q[1]],s[q[top]],y);
            mark=0;
        }
    } 
    
    struct Data{int x,from;
        friend Data operator+(Data a,Data b)
        {
            if(SGT::s[a.x]==SGT::s[b.x]) return (Data){a.x,min(a.from,b.from)};
            if(SGT::s[a.x]>SGT::s[b.x]) return a;
            else return b;
        }
    }s[MN+5];
    struct data{ld a,b,x;
        bool operator <(const data&y)const{return a==y.a?b<y.b:a<y.a;}
    };
    int n,m,fa[MN+5],c[MN+5][2],mark,rt=0,num[MN+5];
    
    void update(int x)
    {
        s[x]=(Data){num[x-1],x-1};
        if(c[x][0]) s[x]=s[x]+s[c[x][0]];
        if(c[x][1]) s[x]=s[x]+s[c[x][1]];    
    }
    
    void rotate(int x,int&k)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(y==k) k=x; else c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x,int&k)
    {
        for(;x!=k;rotate(x,k))
            if(fa[x]!=k) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x],k);
    }
    
    int Split(int l,int r)
    {
        splay(l,rt);
        splay(r+2,c[rt][1]);
        return c[c[rt][1]][0];
    }
    
    void Modify(int x,int k)
    {
        if(x!=k) Modify(c[x][k>x],k);
        update(x);    
    }
    
    void build(int&x,int l,int r,int last)
    {
        if(l>r){x=0;return;}
        int mid=l+r>>1;x=mid;fa[x]=last;
        build(c[x][0],l,mid-1,x);
        build(c[x][1],mid+1,r,x);
        update(x);
    }
    char op[10];
    int main()
    {
        n=read();m=read();
        SGT::cnt=1;SGT::s[0]=-1;SGT::s[1]=INF;
        SGT::ins(SGT::rt,0,0,0);SGT::ins(SGT::rt,1,1,INF);
        for(int i=1;i<=n+2;++i) num[i]=0;
        build(rt,1,n+2,0);
        for(int i=1;i<=m;++i)
        {
            scanf("%s",op+1);
            if(op[1]=='C')
            {
                int a=read(),b=read(),k=read();
                num[k]=SGT::GetID(SGT::rt,num[a],num[b],0,INF);
                if(SGT::mark) SGT::rebuild();
                Modify(rt,k+1);splay(k+1,rt);
            }
            else 
            {
                int l=read(),r=read();
                int x=Split(l,r);
                printf("%d
    ",s[x].from);
            }    
        }
        return 0;
    }
  • 相关阅读:
    团队项目——站立会议DAY14
    团队项目——站立会议DAY13
    团队项目——站立会议DAY12
    团队项目——站立会议 DAY11
    团队项目——站立会议DAY10
    团队项目——站立会议DAY9
    团队项目——站立会议 DAY8
    团队项目——站立会议DAY7
    团队项目——站立会议DAY6
    作业五:团队项目——项目启动及需求分析
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3600.html
Copyright © 2020-2023  润新知