1. 程式人生 > >維護序列[Splay]

維護序列[Splay]

題目描述

請寫一個程式,要求維護一個數列,支援以下 6 種操作:(請注意,格式欄 中的下劃線‘ _ ’表示實際輸入檔案中的空格)

輸入格式:

輸入檔案的第 1 行包含兩個數 N 和 M,N 表示初始時數列中數的個數,M 表示要進行的運算元目。 第 2 行包含 N 個數字,描述初始時的數列。 以下 M 行,每行一條命令,格式參見問題描述中的表格

輸出格式:

對於輸入資料中的 GET-SUM 和 MAX-SUM 操作,向輸出檔案依次列印結 果,每個答案(數字)佔一行。

輸入樣例#1: 

9 8 
2 -6 3 5 1 -5 -3 6 3 
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM

輸出樣例#1: 

-1
10
1
10

說明

你可以認為在任何時刻,數列中至少有 1 個數。

輸入資料一定是正確的,即指定位置的數在數列中一定存在。

50%的資料中,任何時刻數列中最多含有 30 000 個數;

100%的資料中,任何時刻數列中最多含有 500 000 個數。

100%的資料中,任何時刻數列中任何一個數字均在[-1 000, 1 000]內。

100%的資料中,M ≤20 000,插入的數字總數不超過 4 000 000 。

 Splay模板 + 類似線段樹區間合併的東西

#include<bits/stdc++.h>
#define N 5000005
#define lc t[x].ch[0]
#define rc t[x].ch[1]
using namespace std;
int n,m,root,tot,a[N],p[N]; char ch[20];
struct Node{
	int ch[2],fa,val,size;
	int tag,lazy;
	int lmax,rmax,Max,sum;
}t[N];
int read(){
    int cnt=0,f=1;char ch=0;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')f=-1;}
    while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
    return cnt*f;
}
void Update(int x,int d){
	t[x].val=d,t[x].sum=d*t[x].size,t[x].lazy+=d;
	t[x].lmax=t[x].rmax=t[x].Max=max(d,d*t[x].size);
}
void Pushup(int x){
	t[x].size=t[lc].size+t[rc].size+1;
	t[x].sum=t[lc].sum+t[x].val+t[rc].sum;
	t[x].Max=max( max(t[lc].Max,t[rc].Max) , max(t[lc].rmax,0) + t[x].val + max(0,t[rc].lmax) );
	t[x].lmax=max(t[lc].lmax,t[lc].sum + t[x].val + max(0,t[rc].lmax));
	t[x].rmax=max(t[rc].rmax,t[rc].sum + t[x].val + max(0,t[lc].rmax));
}
int Build(int l,int r,int fa){
	if(l>r) return 0;
	int mid=(l+r)>>1,x=++tot; p[x]=mid; t[x].size=1;
	t[x].fa=fa,t[x].lmax=t[x].rmax=t[x].Max=t[x].sum=t[x].val=a[mid];
	lc=Build(l,mid-1,x),rc=Build(mid+1,r,x);
	Pushup(x); return x;
}
void Swap(int x){
	swap(lc,rc);
	swap(t[x].lmax,t[x].rmax);
	t[x].tag^=1;
}
void Pushdown(int x){
	if(t[x].tag){
		if(lc) Swap(lc);
		if(rc) Swap(rc);
		t[x].tag=0;
	}
	if(t[x].lazy){
		if(lc) Update(lc,t[x].lazy);
		if(rc) Update(rc,t[x].lazy);
		t[x].lazy=0;
	} 
}
void Pushpath(int x){
	if(t[x].fa) Pushpath(t[x].fa);
	Pushdown(x);
}
void rotate(int x){
	int y=t[x].fa,z=t[y].fa;
	int k=(t[y].ch[1]==x);
	t[z].ch[t[z].ch[1]==y]=x;
	t[x].fa=z;
	t[y].ch[k]=t[x].ch[k^1];
	t[t[x].ch[k^1]].fa=y;
	t[x].ch[k^1]=y;
	t[y].fa=x;
	Pushup(y),Pushup(x);
}
void Splay(int x,int goal){
	Pushpath(x);
	while(t[x].fa!=goal){
		int y=t[x].fa,z=t[y].fa;
		if(z!=goal)
			(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
		rotate(x); 
	}if(goal==0) root=x;
}
int Find(int x,int k){
	Pushdown(x);
	if(t[lc].size>=k) return Find(lc,k);
	else if(t[lc].size+1<k) return Find(rc,k-t[lc].size-1);
	return x;
}
int main(){
	n=read(),m=read();
	for(int i=2;i<=n+1;i++) a[i]=read();
	a[1]=a[n+2]=-0x3fffffff; root=Build(1,n+2,0);
	while(m--){
		scanf("%s",ch);
		if(ch[0]=='I'){
			int x=read(),T=read(); 
			x=Find(root,x+1); Splay(x,0);
			int y=Find(rc,1); Splay(y,x);
			for(int i=1;i<=T;i++) a[i]=read();
			int o=Build(1,T,y);  
			t[y].ch[0]=o;
			Pushup(y),Pushup(x); 
		}
		if(ch[0]=='D'){
			int x=read(),T=read();
			x=Find(root,x); Splay(x,0);
			int y=Find(rc,T+1); Splay(y,x);
			t[t[y].ch[0]].fa=0,t[y].ch[0]=0;
			Pushup(y),Pushup(x);
		}
		if(ch[2]=='K'){
			int x=read(),T=read(),val=read();
			x=Find(root,x); Splay(x,0);
			int y=Find(rc,T+1); Splay(y,x);
			Update(t[y].ch[0],val); 
			Pushup(y),Pushup(x);
		}
		if(ch[0]=='R'){
			int x=read(),T=read();
			x=Find(root,x); Splay(x,0);
			int y=Find(rc,T+1); Splay(y,x);
			Swap(t[y].ch[0]);
			t[t[y].ch[0]].tag^=1; 
			Pushup(y),Pushup(x);
		}
		if(ch[0]=='G'){
			int x=read(),T=read();
			x=Find(root,x); Splay(x,0);
			int y=Find(rc,T+1);
			Splay(y,x); 
			printf("%d\n",t[t[y].ch[0]].sum);
		}
		if(ch[2]=='X') printf("%d\n",t[root].Max);
	}
	return 0;
}