zoukankan      html  css  js  c++  java
  • poj3580(splay 毒瘤题)

    3: Lydsy1895 SuperMemo

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 15  Solved: 11
    [Submit][Status][Web Board]

    Description

    给出一个初始序列fA1;A2;:::Ang,要求你编写程序支持如下操作: 
    1. ADDxyD:给子序列fAx:::Ayg的每个元素都加上D。例如对f1,2, 3,4,5g执行"ADD 241" 会得到f1,3,4,5,5g。 
    2. REVERSExy:将子序列fAx:::Ayg翻转。例如对f1,2,3,4,5g执行"REVERSE 24"会得到f1,4,3,2,5g。 
    3. REVOLVExyT:将子序列fAx:::Ayg旋转T个单位。例如,对f1,2,3,4,5g执行"REVOLVE 242"会得到f1,3,4,2,5g。 
    4. INSERTxP:在Ax后插入P。例如,对f1,2,3,4,5g执行"INSERT 24"会得到f1,2,4,3,4,5g。 
    5. DELETEx:删去Ax。例如,对f1,2,3,4,5g执行"DELETE 2"会得到f1,3,4,5g。 
    6. MINxy:查询子序列fAx:::Ayg中的最小元素。例如,对于序列f1, 2,3,4,5g,询问"MIN 24"的返回应为2。

    Input

    第一行包含一个整数n,表示初始序列的长度。
    以下n行每行包含一个整数,描述初始的序列。
    接下来一行包含一个整数m,表示操作的数目。以下m行每行描述一个操作。n,m<=10^6

    Output

    对于所有"MIN"操作,输出正确的答案,每行一个。

    Sample Input

    5
    1
    2
    3
    4
    5
    2
    ADD 2 4 1
    MIN 4 5

    Sample Output

    5

    HINT

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define inf 2100000000
    const int maxn=300000+10;
    
    int a[maxn],f[maxn],ch[maxn][2],key[maxn],Min[maxn],Size[maxn],ver[maxn],add[maxn],root;
    int sz;
    
    void Clear(int x){
         f[x]=ch[x][0]=ch[x][1]=key[x]=Size[x]=Min[x]=ver[x]=add[x]=0;
    }
    
    int getself(int x){
         return ch[f[x]][1]==x;
    }
    
    void update(int x){
         Size[x]=Size[ch[x][0]]+Size[ch[x][1]]+1;
         Min[x]=key[x];
         if(ch[x][0]) Min[x]=min(Min[x],Min[ch[x][0]]);
         if(ch[x][1]) Min[x]=min(Min[x],Min[ch[x][1]]);
    }
    
    void pushdown(int x){
         if(x){
            if(ver[x]){
                ver[ch[x][0]]^=1;
                ver[ch[x][1]]^=1;
                swap(ch[x][0],ch[x][1]);
                ver[x]=0;
            }
            if(add[x]){
                add[ch[x][0]]+=add[x],add[ch[x][1]]+=add[x];
                Min[ch[x][0]]+=add[x],Min[ch[x][1]]+=add[x];
                key[ch[x][0]]+=add[x],key[ch[x][1]]+=add[x];
                add[x]=0;
            }
         }
    }
    
    int build(int l,int r,int fa){
        if(l>r) return 0;
        int mid=(l+r)>>1,now=++sz;
        f[sz]=fa,key[sz]=a[mid];
        int tl=build(l,mid-1,now);
        int tr=build(mid+1,r,now);
        ch[now][0]=tl;
        ch[now][1]=tr;
        update(now);
        return now;
    }
    
    int Find(int x){
        int now=root;
        while(1){
            pushdown(now);
            if(x<=Size[ch[now][0]])  now=ch[now][0];
            else {
                x-=Size[ch[now][0]];
                if(x==1) return now;
                now=ch[now][1];
                --x;
            }
        }
    }
    
    void Rotate(int x){
         pushdown(f[x]);
         pushdown(x);
         int old=f[x],oldf=f[old],which=getself(x);
         ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
         ch[x][which^1]=old;f[old]=x;
         f[x]=oldf;
         if(oldf){
            ch[oldf][ch[oldf][1]==old]=x;
         }
         update(old);
         update(x);
    }
    
    void splay(int x,int tar){
         for (int fa;(fa=f[x])!=tar;Rotate(x))
            if(f[fa]!=tar) Rotate( (getself(x)==getself(fa))?fa:x);
        if(!tar) root=x;
    }
    
    int main(){
        char s[20];
        int n,m;
        scanf("%d",&n);
        a[1]=-inf;
        a[n+2]=inf;
        int x,y,d;
        for (int i=1;i<=n;i++) scanf("%d",&a[i+1]);
        root=build(1,n+2,0);
        scanf("%d",&m);
        for (int i=1;i<=m;i++){
            scanf("%s",s);
            switch(s[0]){
               case 'A':
                {
                  scanf("%d%d%d",&x,&y,&d);
                  if(x>y) swap(x,y);
                  int aa=Find(x);
                  int bb=Find(y+2);
                  splay(aa,0);
                  splay(bb,aa);
                  Min[ch[ch[root][1]][0]]+=d;
                  key[ch[ch[root][1]][0]]+=d;
                  add[ch[ch[root][1]][0]]+=d;
                  update(ch[root][1]);
                  update(root);
                  break;
                }
               case 'R':
                {
                    if(s[3]=='E'){
                        scanf("%d%d",&x,&y);
                        if(x==y) continue;
                        if(x>y) swap(x,y);
                        int aa=Find(x);
                        int bb=Find(y+2);
                        splay(aa,0);
                        splay(bb,aa);
                        ver[ch[ch[root][1]][0]]^=1;
                    }
                    else {
                        scanf("%d%d%d",&x,&y,&d);
                        if(x>y) swap(x,y);
                        d%=y-x+1;
                        if(!d) continue;
                        int aa=Find(y-d+1);
                        int bb=Find(y+2);
                        splay(aa,0);
                        splay(bb,aa);
                        int now=ch[ch[root][1]][0];
                        ch[ch[root][1]][0]=0;
                        update(ch[root][1]);
                        update(root);
    
                        aa=Find(x);
                        bb=Find(x+1);
                        splay(aa,0);
                        splay(bb,aa);
                        ch[ch[root][1]][0]=now;
                        f[now]=ch[root][1];
                        update(ch[root][1]);
                        update(root);
                    }
                    break;
                }
               case 'I':
                {
                    scanf("%d%d",&x,&d);
                    int aa=Find(x+1);
                    int bb=Find(x+2);
                    splay(aa,0);
                    splay(bb,aa);
                    ch[ch[root][1]][0]=++sz;
                    f[sz]=ch[root][1];
                    Size[sz]=1;
                    key[sz]=d;
                    Min[sz]=d;
                    update(ch[root][1]);
                    update(root);
                    break;
                }
               case 'D':
                   {
                     scanf("%d",&x);
                     int aa=Find(x);
                     int bb=Find(x+2);
                     splay(aa,0);
                     splay(bb,aa);
                     int del=ch[ch[root][1]][0];
                     Clear(del);
                     ch[ch[root][1]][0]=0;
                     update(ch[root][1]);
                     update(root);
                     break ;
                   }
               case 'M':
                {
                    scanf("%d%d",&x,&y);
                    if(x>y) swap(x,y);
                    int aa=Find(x);
                    int bb=Find(y+2);
                    splay(aa,0);
                    splay(bb,aa);
                    int ans=Min[ch[ch[root][1]][0]];
                    printf("%d
    ",ans);
                    break;
                }
            }
        }
    return 0;
    }
  • 相关阅读:
    CF1313A Fast Food Restaurant
    模板: zkw线段树
    从5个经典工作开始看语义SLAM
    LeetCode题号[200,299]刷题总结
    2020春招实习总结
    LeetCode题号[100,199]刷题总结
    LeetCode题号[1,99]刷题总结
    HashMap源码详解
    动态规划——楼层扔鸡蛋问题
    图论——迪杰斯特拉算法和最小生成树
  • 原文地址:https://www.cnblogs.com/lmjer/p/9212796.html
Copyright © 2011-2022 走看看