SuperMemo
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 11616 Accepted: 3656
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:

  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

Source

POJ Founder Monthly Contest – 2008.04.13, Yao Jinyu
 给定一个数列a1,a2,...an
 * 进行以下6种操作
 * ADD x y D :给第x个数到第y个数加D(增加一个add进行延迟标记)
 * REVERSE x y :反转[x,y]之间的数(伸展树经典操作)
 * REVOLVE x y T:循环右移T次(先把T对长度进行取模,然后就相当于把[y-T+1,y]放在[x,y-T]前面)
 * INSERT x P:在第x个数后面插入P (经典的插入)
 * DELETE x:删除第x个数(删除操作)
 * MIN x y:查询[x,y]之间最小的数(标记)
ac代码
Problem: 3580		User: kxh1995
Memory: 3736K		Time: 1266MS
Language: C++		Result: Accepted

#include<stdio.h>      
#include<string.h>      
#include<iostream>      
#include<algorithm>      
#define min(a,b) (a>b?b:a)      
#define N 200010  
#define Maxn 200010   
#define INF 0x7FFFFFFF      
using namespace std;    
int pre[N],key[N],ch[N][2],root,top,rev[N],num[N],add[N],minv[N],size;    
int st[N];
int a[N];  
void newnode(int &r,int fa,int val)    
{    
	if(top!=-1)
		r=st[top--];
	else
		r=++size;    
    pre[r]=fa;     
    num[r]=1;  
    rev[r]=0; 
	key[r]=minv[r]=val;
    ch[r][0]=ch[r][1]=add[r]=0;    
}    
void pushup(int r)  
{  
    num[r]=num[ch[r][1]]+num[ch[r][0]]+1;  
	minv[r]=min(minv[ch[r][1]],minv[ch[r][0]]);
	minv[r]=min(minv[r],key[r]);
}  
void pushdown(int r)
{  
	if(add[r])
	{
		if(ch[r][0])
		{
			add[ch[r][0]]+=add[r];
			key[ch[r][0]]+=add[r];
			minv[ch[r][0]]+=add[r];
		}
		if(ch[r][1])
		{
			add[ch[r][1]]+=add[r];
			key[ch[r][1]]+=add[r];
			minv[ch[r][1]]+=add[r];
		}
		add[r]=0;
	}
    if(rev[r])  
    {  
		rev[ch[r][0]]^=1;
		rev[ch[r][1]]^=1;
		swap(ch[r][0],ch[r][1]);
        rev[r]=0;  
    }  
}  
void rotate(int x,int kind)    
{    
    int y=pre[x];   
    pushdown(y);  
	pushdown(x);  
    ch[y][!kind]=ch[x][kind];    
    pre[ch[x][kind]]=y;    
    if(pre[y])    
    {    
        ch[pre[y]][ch[pre[y]][1]==y]=x;    
    }    
    pre[x]=pre[y];    
    ch[x][kind]=y;    
    pre[y]=x;    
    pushup(y);  
}    
/*void splay(int r,int goal)   //也行 
{    
    pushdown(r);  
    while(pre[r]!=goal)    
    {    
        if(pre[pre[r]]==goal)    
        {  
            pushdown(pre[r]);  
            pushdown(r);  
            rotate(r,ch[pre[r]][0]==r);   
        }  
        else    
        {    
            int y=pre[r];    
            pushdown(pre[y]);  
            pushdown(y);  
            pushdown(r);  
            int kind=ch[pre[y]][0]==y;    
            if(ch[y][kind]==r)    
            {    
                rotate(r,!kind);    
                rotate(r,kind);    
            }    
            else    
            {    
                rotate(r,kind);    
                rotate(r,kind);    
            }    
        }    
    }    
    pushup(r);  
    if(goal==0)    
        root=r;    
} */ 
void splay(int r,int goal)
{
	if(r!=goal)
	{
		pushdown(r);
		while(pre[r]!=goal)
		{
			if(ch[pre[r]][0]==r)
				rotate(r,1);
			else
				rotate(r,0);
		}
		pushup(r);
		if(!goal)
			root=r;
	}
}
int select(int k)
{
	int x;
	pushdown(root);
	for(x=root;num[ch[x][0]]+1!=k;)
	{
		if(num[ch[x][0]]+1>k)
			x=ch[x][0];
		else
		{
			k-=num[ch[x][0]]+1;
			x=ch[x][1];
		}
		pushdown(x);
	}
	return x;
}
void Add(int x,int y,int val)
{
	int t;
	x=select(x-1);
	y=select(y+1);
	splay(x,0);
	splay(y,x);
	t=ch[y][0];
	add[t]+=val;
	key[t]+=val;
	minv[t]+=val;
	pushup(y);
	pushup(x);
}
void Rev(int x,int y)
{
	x=select(x-1);
	y=select(y+1);
	splay(x,0);
	splay(y,x);
	rev[ch[y][0]]^=1;
}
void revol(int x,int y,int t)
{
	int cnt=y-x+1;
	t%=cnt;
	if(t<0)
		t+=cnt;
	if(t)
	{
		Rev(x,y-t);
		Rev(y-t+1,y);
		Rev(x,y);
	}
}
void build(int &x,int l,int r,int fa)  
{  
    if(l>r)  
        return;  
    int mid=(l+r)>>1;  
    newnode(x,fa,a[mid]);  
    build(ch[x][0],l,mid-1,x);  
    build(ch[x][1],mid+1,r,x);  
    pushup(x);  
} 
void init(int n)
{
	root=size=0;
	top=-1;
	rev[0]=0;
	ch[0][0]=ch[0][1]=0;
	pre[0]=add[0]=num[0]=0;
	key[0]=minv[0]=INF;
	newnode(root,0,INF);
	newnode(ch[root][1],root,INF);
	build(ch[ch[root][1]][0],1,n,ch[root][1]);
	pushup(ch[root][1]);
	pushup(root);
}  
void insert(int x,int val)
{
	int a,b;
	a=select(x);
	b=select(x+1);
	splay(a,0);
	splay(b,a);
	newnode(ch[b][0],b,val);
	pushup(b);
	pushup(a);
} 
void remove(int x)
{
	int a,b;
	a=select(x-1);
	b=select(x+1);
	splay(a,0);
	splay(b,a);
	st[++top]=ch[b][0];
	ch[b][0]=0;
	pushup(b);
	pushup(a);
}
int Min(int x,int y)
{
	x=select(x-1);
	y=select(y+1);
	splay(x,0);
	splay(y,x);
	return minv[ch[y][0]];
}
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		int i;
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		init(n);
		int q;
		scanf("%d",&q);
		while(q--)
		{
			int x,y,val;
			char op[10];
			scanf(" %s",op);
			scanf("%d",&x);
			if(strcmp(op,"ADD")==0)
			{
				scanf("%d%d",&y,&val);
				Add(x+1,y+1,val);
			}
			else
				if(strcmp(op,"REVERSE")==0)
				{
					scanf("%d",&y);
					Rev(x+1,y+1);
				}
				else
					if(strcmp(op,"REVOLVE")==0)
					{
						scanf("%d%d",&y,&val);
						revol(x+1,y+1,val);
					}
					else
						if(strcmp(op,"INSERT")==0)
						{
							scanf("%d",&y);
							insert(x+1,y);
						}
						else
							if(strcmp(op,"DELETE")==0)
							{
								remove(x+1);
							}
							else
								if(strcmp(op,"MIN")==0)
								{
									scanf("%d",&y);
									printf("%d\n",Min(x+1,y+1));
								}
		}
	}
}



更多推荐

POJ 题目3580 SuperMemo(Splay Tree区间加,区间翻转,区间右移,插入删除,区间最小值)