zoukankan      html  css  js  c++  java
  • 平衡树(Splay):Splaytree POJ 3580 SuperMemo

    SuperMemo      
     

    Description

    Your friend, Jackson is invited to a TV show called SuperMemo in which the participant is told to play a memorizing game. At first, the host tells the participant a sequence of numbers, {A1A2, ... An}. Then the host performs a series of operations and queries on the sequence which consists:

    1. ADD x y D: Add D to each number in sub-sequence {Ax ... Ay}. For example, performing "ADD 2 4 1" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5, 5}
    2. REVERSE x y: reverse the sub-sequence {Ax ... Ay}. For example, performing "REVERSE 2 4" on {1, 2, 3, 4, 5} results in {1, 4, 3, 2, 5}
    3. REVOLVE x y T: rotate sub-sequence {Ax ... AyT times. For example, performing "REVOLVE 2 4 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
    4. INSERT x P: insert P after Ax. For example, performing "INSERT 2 4" on {1, 2, 3, 4, 5} results in {1, 2, 4, 3, 4, 5}
    5. DELETE x: delete Ax. For example, performing "DELETE 2" on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
    6. MIN x y: query the participant what is the minimum number in sub-sequence {Ax ... Ay}. For example, the correct answer to "MIN 2 4" on {1, 2, 3, 4, 5} is 2

    To make the show more interesting, the participant is granted a chance to turn to someone else that means when Jackson feels difficult in answering a query he may call you for help. You task is to watch the TV show and write a program giving the correct answer to each query in order to assist Jackson whenever he calls.

    Input

    The first line contains (≤ 100000).

    The following n lines describe the sequence.

    Then follows M (≤ 100000), the numbers of operations and queries.

    The following M lines describe the operations and queries.

    Output

    For each "MIN" query, output the correct answer.

    Sample Input

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

    Sample Output

    5

      
      这也许是我目前见过最全面的平衡树的题目了,相信把这题搞透之后,平衡树也就差不多了,呃。
      tips:这题我交了好多次才AC ~~~

      

      思路其实很简单,主要是程序实现和各种细节给跪了。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 const int maxn=200010;
      6 const int INF=2147483647;
      7 int Min[maxn],key[maxn],fa[maxn],ch[maxn][2];
      8 int flip[maxn],add[maxn],sz[maxn],rt,cnt,n,Q;
      9 
     10 void Push_up(int p){
     11     Min[p]=min(key[p],min(Min[ch[p][0]],Min[ch[p][1]]));
     12     sz[p]=sz[ch[p][0]]+sz[ch[p][1]]+1;
     13 }
     14 
     15 void Add(int p,int d){
     16     if(p){
     17         Min[p]+=d;
     18         key[p]+=d;
     19         add[p]+=d;
     20     }
     21 }
     22 
     23 void Flip(int p){
     24     swap(ch[p][0],ch[p][1]);
     25     flip[p]^=1;
     26 }
     27 
     28 void Push_down(int p){
     29     if(add[p]){
     30         Add(ch[p][0],add[p]);
     31         Add(ch[p][1],add[p]);
     32         add[p]=0;
     33     }
     34     if(flip[p]){
     35         Flip(ch[p][0]);
     36         Flip(ch[p][1]);
     37         flip[p]=0;
     38     }
     39 }
     40 
     41 void Rotate(int x){
     42     int y=fa[x],g=fa[y],c=ch[y][1]==x;
     43     ch[y][c]=ch[x][c^1];
     44     fa[ch[x][c^1]]=y;fa[y]=x;
     45     ch[x][c^1]=y;fa[x]=g;
     46     if(g)
     47         ch[g][ch[g][1]==y]=x;
     48     Push_up(y);    
     49 }
     50     
     51 void Splay(int x,int g=0){
     52     for(int y;(y=fa[x])!=g;Rotate(x))
     53         if(fa[y]!=g)
     54             Rotate((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x);
     55     Push_up(x);
     56     if(!g)
     57         rt=x;
     58 }
     59 
     60 void Make_root(int x,int g=0){
     61     int p=rt;
     62     while(true){
     63         Push_down(p);
     64         if(sz[ch[p][0]]+1==x)break;
     65         if(sz[ch[p][0]]+1<x){
     66             x-=sz[ch[p][0]]+1;
     67             p=ch[p][1];
     68         }
     69         else
     70             p=ch[p][0];
     71     }
     72     Splay(p,g);
     73 }
     74 
     75 int Build(int pre,int l,int r){
     76     if(l>r)return 0;
     77     int mid=(l+r)>>1;
     78     ch[mid][0]=Build(mid,l,mid-1);
     79     if(mid>1&&mid<n)
     80         scanf("%d",&key[mid]);
     81     else    
     82         key[mid]=INF;
     83     Min[mid]=key[mid];
     84     fa[mid]=pre;sz[mid]=1;
     85     ch[mid][1]=Build(mid,mid+1,r);
     86     Push_up(mid);
     87     return mid;    
     88 }
     89 
     90 int main(){
     91     Min[0]=2147482647;
     92     scanf("%d",&n);n+=2;
     93     rt=Build(0,1,n);cnt=n;
     94     scanf("%d",&Q);
     95     char s[10];int a,b,x;
     96     while(Q--){
     97         scanf("%s",s);
     98         if(!strcmp(s,"ADD")){
     99             scanf("%d%d%d",&a,&b,&x);a++;b++;
    100             Make_root(a-1);
    101             Make_root(b+1,rt);
    102             Push_down(rt);
    103             Push_down(ch[rt][1]);
    104             Add(ch[ch[rt][1]][0],x);
    105         }
    106         else if(!strcmp(s,"MIN")){
    107             scanf("%d%d",&a,&b);a++;b++;
    108             Make_root(a-1);
    109             Make_root(b+1,rt);
    110             Push_down(rt);
    111             Push_down(ch[rt][1]);
    112             printf("%d
    ",Min[ch[ch[rt][1]][0]]);
    113         }
    114         else if(!strcmp(s,"DELETE")){
    115             scanf("%d",&x);x++;
    116             Make_root(x-1);
    117             Make_root(x+1,rt);
    118             ch[ch[rt][1]][0]=0;
    119             Push_up(ch[rt][1]);
    120             Push_up(rt);
    121         }
    122         else if(!strcmp(s,"REVERSE")){
    123             scanf("%d%d",&a,&b);a++;b++;
    124             Make_root(a-1);
    125             Make_root(b+1,rt);
    126             Flip(ch[ch[rt][1]][0]);
    127         }
    128         else if(!strcmp(s,"INSERT")){
    129             scanf("%d%d",&a,&x);a++;
    130             Make_root(a);
    131             Make_root(a+1,rt);
    132             int p=++cnt;sz[p]=1;
    133             ch[ch[rt][1]][0]=p;
    134             key[p]=Min[p]=x;
    135             fa[p]=ch[rt][1];
    136             Push_up(ch[rt][1]);
    137             Push_up(rt);
    138         }
    139         else if(!strcmp(s,"REVOLVE"))
    140         {
    141             scanf("%d%d%d",&a,&b,&x);a++;b++;
    142             Make_root(a-1);
    143             Make_root(b+1,rt);
    144             x%=b-a+1;
    145             if(x){
    146                 Make_root(b-x);
    147                 Make_root(b+1,rt);
    148                 int tmp=ch[ch[rt][1]][0];
    149                 ch[ch[rt][1]][0]=0;
    150                 Push_up(ch[rt][1]);
    151                 Push_up(rt);
    152                 Make_root(a-1);
    153                 Make_root(a,rt);
    154                 ch[ch[rt][1]][0]=tmp;
    155                 fa[tmp]=ch[rt][1];
    156                 Push_up(ch[rt][1]);
    157                 Push_up(rt);
    158             }
    159         }
    160     }
    161     return 0;
    162 }
      时隔多月,我学会了treap,再AC了一遍。
      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <cstdio>
      5 using namespace std;
      6 const int maxn=200010;
      7 const int INF=2147483647;
      8 int key[maxn],flip[maxn],add[maxn],cnt,rt;
      9 int Min[maxn],sz[maxn],ch[maxn][2],fix[maxn];
     10 int x,y,z,t1,t2;
     11 struct Treap{
     12     void Init(){
     13         Min[0]=INF;
     14         //srand(time(NULL)); poj上不能在G++上用这个,否则RE
     15     }
     16     
     17     int Newnode(int v){
     18         sz[++cnt]=1;
     19         Min[cnt]=key[cnt]=v;
     20         flip[cnt]=add[cnt]=0;
     21         ch[cnt][0]=ch[cnt][1]=0;
     22         fix[cnt]=rand();
     23         return cnt;
     24     }
     25     
     26     void Push_up(int x){
     27         sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
     28         Min[x]=min(min(Min[ch[x][0]],Min[ch[x][1]]),key[x]);
     29     }
     30     
     31     void Flip(int x){
     32         swap(ch[x][0],ch[x][1]);
     33         flip[x]^=1;
     34     }
     35     
     36     void Add(int x,int d){
     37         if(!x)return;
     38         key[x]+=d;
     39         Min[x]+=d;
     40         add[x]+=d;
     41     }
     42     
     43     void Push_down(int x){
     44         if(add[x]){
     45             Add(ch[x][0],add[x]);
     46             Add(ch[x][1],add[x]);
     47             add[x]=0;
     48         }
     49         if(flip[x]){
     50             Flip(ch[x][0]);
     51             Flip(ch[x][1]);
     52             flip[x]=0;
     53         }
     54     }
     55     
     56     int Merge(int x,int y){
     57         if(!x||!y)return x|y;
     58         Push_down(x);
     59         Push_down(y);
     60         if(fix[x]<=fix[y]){
     61             ch[x][1]=Merge(ch[x][1],y);
     62             Push_up(x);
     63             return x;
     64         }
     65         else{
     66             ch[y][0]=Merge(x,ch[y][0]);
     67             Push_up(y);
     68             return y;
     69         }
     70     }
     71     
     72     void Split(int x,int k){
     73         Push_down(x);
     74         if(k>sz[x]){t1=x;t2=0;return;}
     75         
     76         if(sz[ch[x][0]]+1==k){
     77             t1=ch[x][0];t2=x;
     78             ch[x][0]=0;
     79             Push_up(x);
     80             return;
     81         }
     82         
     83         if(sz[ch[x][0]]+1<k){
     84             k-=sz[ch[x][0]]+1;
     85             Split(ch[x][1],k);
     86             ch[x][1]=t1;t1=x;
     87             Push_up(x);
     88         }
     89         
     90         else{
     91             Split(ch[x][0],k);
     92             ch[x][0]=t2;t2=x;
     93             Push_up(x);
     94         }
     95     }
     96     
     97     
     98     void Insert(int k,int v){
     99         Split(rt,k+1);
    100         t1=Merge(t1,Newnode(v));
    101         rt=Merge(t1,t2);
    102     }
    103     
    104     void Delete(int k){
    105         int tmp;
    106         Split(rt,k);tmp=t1;
    107         Split(t2,2);t1=tmp;
    108         rt=Merge(t1,t2);
    109     }
    110     
    111     void Divide(int l,int r){
    112         Split(rt,l);x=t1;
    113         Split(t2,r-l+2);y=t1;z=t2;
    114     }
    115     
    116     void Converge(){
    117         x=Merge(x,y);
    118         rt=Merge(x,z);
    119     }
    120     
    121     void Add(int l,int r,int d){
    122         Divide(l,r);Add(y,d);
    123         Converge();
    124     }
    125     
    126     void Reverse(int l,int r){
    127         Divide(l,r);Flip(y);
    128         Converge();
    129     }
    130     
    131     void Revolve(int l,int r,int k){
    132         Divide(l,r);
    133         k%=sz[y];
    134         if(k){
    135             Split(y,sz[y]-k+1);
    136             y=Merge(t2,t1);
    137         }        
    138         Converge();
    139     }
    140     
    141     int Query(int l,int r){
    142         Divide(l,r);
    143         int ret=Min[y];
    144         Converge();
    145         return ret;
    146     }
    147 }T;
    148 
    149 int n,Q;
    150 char op[10];
    151 
    152 int main(){
    153     T.Init();
    154     scanf("%d",&n);
    155     for(int i=1,a;i<=n;i++){
    156         scanf("%d",&a);
    157         T.Insert(i,a);
    158     }
    159     int l,r,k;
    160     scanf("%d",&Q);
    161     while(Q--){
    162         scanf("%s",op);
    163         if(!strcmp(op,"ADD")){
    164             scanf("%d%d%d",&l,&r,&k);
    165             T.Add(l,r,k);
    166         }
    167         else if(!strcmp(op,"REVERSE")){
    168             scanf("%d%d",&l,&r);
    169             T.Reverse(l,r);
    170         }
    171         else if(!strcmp(op,"REVOLVE")){
    172             scanf("%d%d%d",&l,&r,&k);
    173             T.Revolve(l,r,k);
    174         }
    175         else if(!strcmp(op,"INSERT")){
    176             scanf("%d%d",&l,&k);
    177             T.Insert(l,k);
    178         }
    179         else if(!strcmp(op,"DELETE")){
    180             scanf("%d",&k);
    181             T.Delete(k);
    182         }
    183         else if(!strcmp(op,"MIN")){
    184             scanf("%d%d",&l,&r);
    185             printf("%d
    ",T.Query(l,r));
    186         }
    187     }
    188     return 0;
    189 }

      有些地方没打好,很丑……

      决定日后整理为模板。




    尽最大的努力,做最好的自己!
  • 相关阅读:
    jquery实现checkbox列表的全选不选
    SQL server 无法更新标识列
    如何设置IIS程序池的回收时间,才能最大程度的减少对用户的影响?
    混合式App开发 Apicloud 官方iPhone X 适配
    C# 加密解密以及sha256不可逆加密案例
    C#排队处理DEMO
    vs中如何统计整个项目的代码行数
    ApiCloud利用NVTabBar模块快速搭建起APP的框架
    走进异步编程的世界--async/await项目使用实战
    H5开发APP考题和答案
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5203538.html
Copyright © 2011-2022 走看看