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;
}