[BZOJ]1895: Pku3580 supermemo

题解:splay裸题   直接扒了以前poj的代码...ac+1

#include <iostream>
#include <algorithm>
#include <cstdio>
#define N 400005
#define rl ch[ch[root][1]][0]
#define lr ch[ch[root][0]][1]
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}
int size[N],pre[N],ch[N][2];
ll add[N],flag[N],key[N],Min[N];
int a[N],s[N];
int root,cnt1,cnt2,n;
void newnode(int &x,int fa,int vul){
	if(cnt2) x=s[cnt2--];
	else x=(++cnt1);
	size[x]=1;pre[x]=fa;Min[x]=key[x]=vul;
	ch[x][0]=ch[x][1]=add[x]=flag[x]=0;
}
void reverse(int x){
	if(!x) return ;
	swap(ch[x][0],ch[x][1]);
	flag[x]^=1;
}
void push(int x){
	if(add[x]){
		if(ch[x][0]) {
		add[ch[x][0]]+=add[x];Min[ch[x][0]]+=add[x];key[ch[x][0]]+=add[x];}
		if(ch[x][1]) {
		add[ch[x][1]]+=add[x];Min[ch[x][1]]+=add[x];key[ch[x][1]]+=add[x];}
		add[x]=0;
	}
	if(flag[x]){
		if(ch[x][0]) reverse(ch[x][0]);
		if(ch[x][1]) reverse(ch[x][1]);
		flag[x]=0;
	}
}
void up(int x){
	size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
	Min[x]=min(key[x],min(Min[ch[x][0]],Min[ch[x][1]]));
}
void rotate(int x,int kind){
	int y=pre[x];
	push(y);push(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];pre[y]=x;ch[x][kind]=y;
	up(y);up(x);
}
void splay(int x,int goal){
	push(x);
	while(pre[x]!=goal){
		if(pre[pre[x]]==goal){
			push(pre[x]);push(x);
			int kind=ch[pre[x]][0]==x;
			rotate(x,kind);
		}
		else{
			int y=pre[x];
			push(pre[y]);push(y);push(x);
			int kind=ch[pre[y]][0]==y;
			if(ch[y][kind]==x){
				rotate(x,!kind);rotate(x,kind);
			}
			else{
				rotate(y,kind);
				rotate(x,kind);
			}
		}
	}
	if(goal==0) root=x;
	up(x);
}
int find1(int x,int t){
	push(x);
	if(t==size[ch[x][0]]+1) return x;
	else if(t<size[ch[x][0]]+1) return find1(ch[x][0],t);
	else return find1(ch[x][1],t-size[ch[x][0]]-1);
	up(x);
}
void Add(int l,int r,int vul){
	splay(find1(root,l),0);splay(find1(root,r+2),root);
	add[rl]+=vul;Min[rl]+=vul;key[rl]+=vul;
	up(ch[root][1]);up(root);
}
void update(int l,int r){
	splay(find1(root,l),0);splay(find1(root,r+2),root);
	reverse(rl);
	up(ch[root][1]);up(root);
}
void revolve(int l,int r,int t){
	int len=t%(r-l+1);
	if(!len) return ;
	splay(find1(root,r-len+1),0);
	splay(find1(root,r+2),root);
	up(ch[root][1]);up(root);
	int tmp=rl;
	rl=0;
	splay(find1(root,l),0);
	splay(find1(root,l+1),root);
	pre[tmp]=ch[root][1];
	rl=tmp;
	up(ch[root][1]);
	up(root);
}
void insert(int t,int p){
	splay(find1(root,t+1),0);
	splay(find1(root,t+2),root);
	newnode(rl,ch[root][1],p);
	up(ch[root][1]);up(root);
}
void delet(int t){
	splay(find1(root,t),0);
	splay(find1(root,t+2),root);
	s[++cnt2]=rl;
	pre[rl]=0;
	rl=0;
	up(ch[root][1]);up(root);
}
int min1(int l,int r){
	splay(find1(root,l),0);
	splay(find1(root,r+2),root);
	return Min[rl];
}
void built(int &x,int l,int r,int fa){
	if(l>r) return ;
	int mid=(l+r)>>1;
	newnode(x,fa,a[mid]);
	built(ch[x][0],l,mid-1,x);
	built(ch[x][1],mid+1,r,x);	
	up(x);
}
void init(){
	for(int i=1;i<=n;i++) a[i]=read();
	root=cnt1=cnt2=0;
	size[root]=pre[root]=add[root]=flag[root]=ch[root][0]=ch[root][1]=0;
	Min[root]=INF;
	newnode(root,0,INF);
	newnode(ch[root][1],root,INF);
	built(rl,1,n,ch[root][1]);
	up(ch[root][1]);up(root);
}
int main(){
		n=read();
		init();
		int q=read();char str[102];
		int t1,t2,t3;
		while(q--){
			scanf("%s",str);
			if(str[0]=='A'){
				t1=read();t2=read();t3=read();
				Add(t1,t2,t3);
			} 
			else if(str[0]=='R'&&str[3]=='E'){
				t1=read();t2=read();
				update(t1,t2);
			}
			else if(str[0]=='R'){
				t1=read();t2=read();t3=read();
				revolve(t1,t2,t3);
			}
			else if(str[0]=='I'){
				t1=read();t2=read();
				insert(t1,t2);
			}
			else if(str[0]=='D'){
				t1=read();
				delet(t1);
			}
			else if(str[0]=='M'){
				t1=read();t2=read();
				printf("%d\n",min1(t1,t2));
			}
		}
	return 0;
}

  

1895: Pku3580 supermemo

Time Limit: 15 Sec  Memory Limit: 64 MB
Submit: 643  Solved: 245
[Submit][Status][Discuss]

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行每行描述一个操作。

Output

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

Sample Input

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

Sample Output

5

HINT

输入、输出以及中间运算结果均不会超过32位整数。
对于30%的数据,n;m 6 1000;
对于100%的数据,n;m 6 100000。

posted @ 2019-01-30 02:15  wang9897  阅读(173)  评论(0编辑  收藏  举报