POJ 3580 SuperMemo

SuperMemo

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 15653 Accepted: 4935
Case Time Limit: 2000MS
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, {A1, A2, … An}. Then the host performs a series of operations and queries on the sequence which consists:
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}
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}
REVOLVE x y T: rotate sub-sequence {Ax … Ay} T times. For example, performing “REVOLVE 2 4 2” on {1, 2, 3, 4, 5} results in {1, 3, 4, 2, 5}
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}
DELETE x: delete Ax. For example, performing “DELETE 2” on {1, 2, 3, 4, 5} results in {1, 3, 4, 5}
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 n (n ≤ 100000).
The following n lines describe the sequence.
Then follows M (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
Source
POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int INF = 1000000000;
struct Node{
    int val,size,lazy,Min;
    bool rev;//标记是否反转
    Node *ch[2],*fa;
    void init(int x){
        fa = ch[0] = ch[1] = NULL;  
        Min = val = x;
        lazy=0;size=1;
        rev=false;
    }
}nstack[210010];
Node* root;
int n,m,scnt;
int GetSize(Node *&cur){ return cur ? cur->size : 0; }
void PushDown(Node *&x){
    if(!x) return;
    if(x->lazy){
        int w=x->lazy;
        x->val += w;
        if(x->ch[0]){
            x->ch[0]->lazy += w;
            x->ch[0]->Min += w;
        }
        if(x->ch[1]){
            x->ch[1]->lazy += w;
            x->ch[1]->Min += w;
        }
        x->lazy = 0;
    }
    if(x->rev){
        Node *t=x->ch[0];
        x->ch[0] = x->ch[1];
        x->ch[1] = t;
        x->rev = false;
        if(x->ch[0]) x->ch[0]->rev ^= 1;
        if(x->ch[1]) x->ch[1]->rev ^= 1;
    }
}
void UpDate(Node *&cur){
    if(!cur) return;
    cur->size = 1;
    cur->Min = cur->val;
    if(cur->ch[0]){
        cur->Min = min(cur->Min,cur->ch[0]->Min);
        cur->size += cur->ch[0]->size;
    }
    if(cur->ch[1]){
        cur->Min = min(cur->Min,cur->ch[1]->Min);
        cur->size += cur->ch[1]->size;
    }
}
void Rotate(Node *&x,int c){//c==0 左旋 c==1右旋 
    Node *y=x->fa;
    //PushDown(y);
    //PushDown(x);
    //PushDown(x->ch[c]);
    y->ch[!c] = x->ch[c];
    if(x->ch[c] != NULL) x->ch[c]->fa = y;
    x->fa = y->fa;
    if(y->fa != NULL)
        if(y->fa->ch[0] == y) y->fa->ch[0] = x;
        else y->fa->ch[1] = x;
    x->ch[c] = y; y->fa = x;
    //UpDate(y);
    if(y == root) root=x;
}
void Splay(Node *&cur,Node *&f){//将cur转到f的位置 
    for(PushDown(cur); cur != f ;){
        if(cur->fa == f) 
            if(f->ch[0] == cur) Rotate(cur,1);
            else Rotate(cur,0);
        else {
            Node *y = cur->fa,*z = y->fa;
            if(z->ch[0] == y)
                if(y->ch[0] == cur)
                    Rotate(y,1),Rotate(cur,1);//yi
                else Rotate(cur,0),Rotate(cur,1);//zhi
            else if(y->ch[1] == cur)
                    Rotate(y,0),Rotate(cur,0);//yi
                else Rotate(cur,1),Rotate(cur,0);//zhi
            if(z==f) break;
        }
        //UpDate(cur);
    }
    //UpDate(cur);
}
void Select(int k,Node *&x){
    int tmp;Node *t;
    for(t=root;;){
        PushDown(t);
        tmp=GetSize(t->ch[0]);
        if(k == tmp+1) break;
        else if(k <= tmp) t=t->ch[0];
        else k -= (tmp+1),t=t->ch[1];
    }
    PushDown(t);
    Splay(t,x);
}
void Insert(int pos,int value){
    Select(pos+1,root);
    Select(pos+2,root->ch[1]);
    Node *t=nstack+scnt++,*x=root->ch[1];
    PushDown(root);
    PushDown(x);
    t->init(value);
    t->ch[1] = x;
    x->fa = t;
    root->ch[1]=t;
    t->fa = root;
    Splay(x,root);
}
void Add(int a,int b,int d){
    Select(a,root);
    Select(b+2,root->ch[1]);
    Node *x=root->ch[1]->ch[0];
    PushDown(x);
    UpDate(x);
    x->Min += d;x->lazy += d;
    Splay(x,root);
}
void Reverse(int a,int b){//鍖洪棿缈昏浆
    Select(a,root);Select(b+2,root->ch[1]);
    root->ch[1]->ch[0]->rev ^= 1;
    Node *x=root->ch[1]->ch[0];
    Splay(x,root);
}
void Resolve(int a,int b,int k){//鍖洪棿缈昏浆K娆?
    Node *p1,*p2;
    Select(a,root);Select(b+2,root->ch[1]);
    Select(b+1-k,root->ch[1]->ch[0]);
    p1=root->ch[1]->ch[0];
    PushDown(p1);
    p2=p1->ch[1];
    p1->ch[1]=NULL;
    Select(a+1,root->ch[1]->ch[0]);
    p1=root->ch[1]->ch[0];
    PushDown(p1);
    p1->ch[0]=p2;
    p2->fa = p1;
    Splay(p2,root);
}
int GetMin(int a,int b){
    Select(a,root);Select(b+2,root->ch[1]);
    Node* x=root->ch[1];
    PushDown(x);
    x=x->ch[0];
    PushDown(x);
    UpDate(x);
    return x->Min;
}
int Delete(int pos){
    Select(pos,root);
    Select(pos+2,root->ch[1]);
    PushDown(root->ch[1]);
    root->ch[1]->ch[0] = NULL;
    Node* x=root->ch[1];
    Splay(x,root);
}
int main(){
    scanf("%d",&n);scnt=0;
    root=nstack+scnt++;
    root->init(INF);
    root->ch[1]=nstack+scnt++;  
    root->ch[1]->init(INF);
    for(int x,i=0;i<n;i++){
        scanf("%d",&x);
        Insert(i,x);
    }
    scanf("%d",&m);
    char s[20];
    while(m--){
        int a,b,c,k;
        scanf("%s",s);
        if(s[0]=='A'){
            scanf("%d%d%d",&a,&b,&c);
            Add(a,b,c);
        }
        else if(s[0]=='R'){
            scanf("%d%d",&a,&b);
            if(s[3]=='E') Reverse(a,b);
            else{
                scanf("%d",&k);
                int tn=b-a+1;
                k=(k%tn+tn)%tn;
                if(a==b||k==0) continue;
                Resolve(a,b,k);
            }
        }       
        else if(s[0]=='I'){
            scanf("%d%d",&a,&c);
            Insert(a,c);
        } else if(s[0]=='D'){
            scanf("%d",&a);
            Delete(a);
        }
        else {
            scanf("%d%d",&a,&b);
            printf("%d\n",GetMin(a,b));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值