• 【Luogu】P1110报表统计(Splay)


      题目链接

      SBT,我居然没看出来。

      就是插入的时候考虑向平衡树里插两个差值,删一个差值。

      另一个操作就是维护某元素和其前驱后继的差值最小值就行了。

      然后Splay超时了……

      (貌似Splay超时了之后我都是修改splay操作的频率暴力硬卡,而不是考虑换一种思路……

      然后就被我卡过了。

      

    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<cstdlib>
    #define maxn 700010
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int CNT=0;
    struct Splay{
        struct Node{
            int val,fa,e[2],size,sum;
        }tree[maxn];
        int point,tot,root;
        Splay(){point=tot=root=0;    }
        inline void update(int x){    tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+tree[x].sum;    }
        inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
        inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
        inline void rotate(int x){
            int y=tree[x].fa;int r=tree[y].fa;
            if(y==root)    root=x;
            int sony=iden(x);int sonr=iden(y);
            int b=tree[x].e[sony^1];
            connect(b,y,sony);
            connect(y,x,sony^1);
            connect(x,r,sonr);
            update(y);    update(x);
        }
        void splay(int pos,int to){
            to=tree[to].fa;
            while(tree[pos].fa!=to){
                if(tree[tree[pos].fa].fa==to)    rotate(pos);
                else
                    if(iden(pos)==iden(tree[pos].fa)){
                        rotate(tree[pos].fa);
                        rotate(pos);
                    }
                    else{    rotate(pos);    rotate(pos);    }
            }
        }
        int create(int val,int fa){
            tree[++tot].val=val;    tree[tot].fa=fa;
            tree[tot].size=tree[tot].sum=1;
            return tot;
        }
        int build(int val){
            point++;
            if(root==0){    root=create(val,0);    return root;    }
            int now=root;
            while(1){
                tree[now].size++;
                if(tree[now].val==val){    tree[now].sum++;    return now;    }
                int nxt=tree[now].val>val?0:1;
                if(tree[now].e[nxt]==0){
                    connect(create(val,now),now,nxt);
                    update(now);
                    return tot;
                }
                now=tree[now].e[nxt];
            }
        }
        void insert(int val){
            int p=build(val);
            if(++CNT=30){
                CNT=0;
                splay(p,root);
            }
        }
        int find(int val){
            int now=root;
            while(now){
                if(tree[now].val==val)    return now;
                int nxt=val<tree[now].val?0:1;
                now=tree[now].e[nxt];
            }
            return 0;
        }
        inline void dele(int x){
            tree[x].e[1]=tree[x].e[0]=tree[x].fa=0;
            if(x==tot)    tot--;
        }
        void pop(int val){
            int deal=find(val);
            if(deal==0)    return;
            splay(deal,root);
            if(tree[deal].sum>1){
                tree[deal].size--;    tree[deal].sum--;
                return;
            }
            if(tree[deal].e[0]==0){
                root=tree[deal].e[1];
                tree[root].fa=0;
            }
            else{
                int le=tree[deal].e[0];
                while(tree[le].e[1])    le=tree[le].e[1];
                splay(le,tree[deal].e[0]);
                connect(tree[deal].e[1],le,1);    connect(le,0,1);
                update(le);
                root=le;
            }
            dele(deal);
        }
        int rank(int val){
            int now=root,ans=0;
            while(now){
                if(tree[now].val==val)    return ans+tree[tree[now].e[0]].size+1;
                int nxt=val<tree[now].val?0:1;
                if(nxt==0)    now=tree[now].e[0];
                else{
                    ans+=tree[tree[now].e[0]].size+tree[now].sum;
                    now=tree[now].e[1];
                }
            }
        }
        inline int arank(){
            int now=root;
            while(tree[now].e[0])   now=tree[now].e[0];
            if(++CNT==30){
                splay(now,root);
                CNT=0;
            }
            return tree[now].val;
        }
        int lower(int val){
            int ans=-700000000,now=root;
            while(now){
                if(tree[now].val==val){
                    splay(now,root);
                    return val;
                }
                if(tree[now].val<val&&tree[now].val>ans)    ans=tree[now].val;
                if(tree[now].val>val)        now=tree[now].e[0];
                else                        now=tree[now].e[1];
            }
            return ans;
        }
        int upper(int val){
            int ans=700000000,now=root;
            while(now){
                if(tree[now].val==val)    return val;
                if(tree[now].val>val&&tree[now].val<ans)    ans=tree[now].val;
                if(tree[now].val<val)        now=tree[now].e[1];
                else                        now=tree[now].e[0];
            }
            return ans;
        }
    }s,d;
    
    int q[maxn];
    int w[maxn];
    int ans=700000000;
    int main(){
        int n=read(),m=read();
        for(int i=1;i<=n;++i){
            q[i]=w[i]=read();
            if(i!=1)    s.insert(abs(q[i]-q[i-1]));
            int now=min(abs(d.lower(q[i])-q[i]),abs(d.upper(q[i])-q[i]));
            d.insert(q[i]);
            if(now<ans)    ans=now;
        }
        for(register int i=1;i<=m;++i){
            char ch[20];
            scanf("%s",ch);
            switch(ch[4]){
                case 'R':{
                    int a=read(),b=read();
                    s.pop(abs(w[a]-q[a+1]));
                    s.insert(abs(w[a]-b));
                    s.insert(abs(b-q[a+1]));
                    w[a]=b;
                    int now=min(abs(d.lower(b)-b),abs(d.upper(b)-b));
                    if(now<ans)    ans=now;
                    d.insert(b);
                    break;
                }
                case 'G':printf("%d
    ",s.arank());    break;
                case 'S':printf("%d
    ",ans);    break;
            }
        }
        return 0;
    }
  • 相关阅读:
    【hdu4057】 恨7不成妻
    【hdu3709】 Balanced Number
    【hdu3555】 Bomb
    【hdu2809】 不要62
    【bzoj3992】 SDOI2015—序列统计
    【uoj125】 NOI2013—书法家
    【bzoj1833】 ZJOI2010—count 数字计数
    【bzoj1026】 SCOI2009—windy数
    【bzoj2780】 Sevenk Love Oimaster
    【bzoj3930】 CQOI2015—选数
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8302779.html
Copyright © 2020-2023  润新知