【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\n",s.arank());    break;
            case 'S':printf("%d\n",ans);    break;
        }
    }
    return 0;
}

 

posted @ 2018-01-17 14:38  Konoset  阅读(169)  评论(0编辑  收藏  举报