SPOJ 4487. Can you answer these queries VI(GSS6 Splay tree)

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove

题目:给出4种操作

在某个位置,插入一个数

将某个位置的数删掉

将某个位置的数修改

查询某个区间的最大子段和

http://www.spoj.pl/problems/GSS6/ 

由于有添加和删除,线段树不好处理,其实是可以的,离线读入

Splay对于添加和删除比较方便吧

比较裸的Splay,哭瞎

从WA到TLE,WA的原因是初始化为0了,最大子段和可以是负的

TLE的一点优化貌似是写成结构体,底层优化

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<algorithm>
#define N 210005
#define inf 100000000
#define MOD 100000007
#define LL long long
#define Key_value ch[ch[root][1]][0]
#define _match(a,b) ((a)==(b))
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int n,q,a[N];
struct Splay_tree{
	int size[N],pre[N],val[N],ans[N],lx[N],rx[N],sum[N];
	int ch[N][2],tot1,root,s[N],tot2;
	//debug部分copy from hh
    void Treaval(int x) {
        if(x) {
            Treaval(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2c \n",x,ch[x][0],ch[x][1],pre[x],size[x],val[x]);
            Treaval(ch[x][1]);
        }
    }
    void debug() {printf("%d\n",root);Treaval(root);}
    //以上Debug
	inline void NewNode(int &r,int k,int father){
        if(tot2) r=s[tot2--];
		else r=++tot1;
        ch[r][0]=ch[r][1]=0;
		pre[r]=father;
		size[r]=1;
		val[r]=ans[r]=lx[r]=rx[r]=sum[r]=k;
	}
	inline void Push_Up(int x){
		int l=ch[x][0],r=ch[x][1];
		size[x]=size[l]+size[r]+1;
		sum[x]=sum[l]+sum[r]+val[x];
		lx[x]=max(lx[l],sum[l]+val[x]+max(lx[r],0));
		rx[x]=max(rx[r],sum[r]+val[x]+max(rx[l],0));
		ans[x]=max(max(ans[l],ans[r]),val[x]+max(lx[r],0)+max(rx[l],0));
	}
	inline void Bulid(int &r,int L,int R,int father){
		if(L>R)
			return ;
		int mid=(L+R)/2;
		NewNode(r,a[mid],father);
		Bulid(ch[r][0],L,mid-1,r);
		Bulid(ch[r][1],mid+1,R,r);
		Push_Up(r);
	}
	inline void Init(){
		tot1=tot2=root=0;
		ch[root][0]=ch[root][1]=pre[root]=size[root]=sum[0]=0;
		lx[root]=rx[root]=val[root]=ans[root]=-inf;
		NewNode(root,-inf,0);
		NewNode(ch[root][1],-inf,root);
		Bulid(Key_value,1,n,ch[root][1]);
		Push_Up(ch[root][1]);
		Push_Up(root);
	}
	inline void Rotate(int x,int kind){
   		int y=pre[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;
		Push_Up(y);
	}
    inline void Splay(int r,int goal){
		while(pre[r]!=goal){
			if(pre[pre[r]]==goal)
				Rotate(r,ch[pre[r]][0]==r);
			else{
				int y=pre[r];
				int kind=(ch[pre[y]][0]==y);
				if(ch[y][kind]==r){
					Rotate(r,!kind);
					Rotate(r,kind);
				}
				else{
					Rotate(y,kind);
					Rotate(r,kind);
				}
			}
		}
		Push_Up(r);
		if(goal==0) root=r;
	}
	inline void RotateTo(int k, int goal) {
		int x=root;
		while(k!=size[ch[x][0]]+1){
			if (k<=size[ch[x][0]]){
				x=ch[x][0];
			}else{
				k-=(size[ch[x][0]]+1);
				x=ch[x][1];
			}
		}
		Splay(x,goal);
	}
	inline int Get_Kth(int r,int k){
		int t=size[ch[r][0]]+1;
		if(t==k) return r;
		if(t>k) return Get_Kth(ch[r][0],k);
		else return Get_Kth(ch[r][1],k-t);
	}
	inline void Insert(int pos,int size){
		RotateTo(pos,0);
		RotateTo(pos+1,root);
		NewNode(Key_value,size,ch[root][1]);
		Push_Up(ch[root][1]);
		Push_Up(root);
	}
	inline void Delete(int pos){
		RotateTo(pos,0);
		RotateTo(pos+2,root);
		Key_value=0;
		Push_Up(ch[root][1]);
		Push_Up(root);
	}
	inline void Replace(int pos,int m){
		int x=Get_Kth(root,pos+1);
		val[x]=m;
		Splay(x,0);
	}
	inline int Query(int x,int y){
		RotateTo(x,0);
		RotateTo(y+2,root);
		return ans[Key_value];
	}
	inline void InOrder(int r){
		if(r==0)
			return;
		InOrder(ch[r][0]);
		printf("%d\n",val[r]);
		InOrder(ch[r][1]);
	}
	inline void Print(){
		RotateTo(1,0);
		RotateTo(n+2,root);
		InOrder(Key_value);
	}
}splay;
//外挂忽略
char CHAR() {
     char res;
     while (res = getchar(), !isalpha(res));
     return res;
}
inline void scanf_(int &num){
    char in;
    bool neg=false;
    while(((in=getchar()) > '9' || in<'0') && in!='-') ;
    if(in=='-'){
        neg=true;
        while((in=getchar()) >'9' || in<'0');
    }
    num=in-'0';
    while(in=getchar(),in>='0'&&in<='9')
        num*=10,num+=in-'0';
    if(neg)
        num=0-num;
}
inline void printf_(int num){
    bool flag=false;
    if(num<0){
        putchar('-');
        num=-num;
    }
    int ans[10],top=0;
    while(num!=0){
        ans[top++]=num%10;
        num/=10;
    }
    if(top==0)
        putchar('0');
    for(int i=top-1;i>=0;i--){
        char ch=ans[i]+'0';
        putchar(ch);
    }
    putchar('\n');
}
int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++)
		   scanf_(a[i]);
        splay.Init();
        scanf_(q);
        while(q--){
			char ch=CHAR();
			int pos,m;
			if(ch=='I'){
				n++;
				scanf_(pos);scanf_(m);
				splay.Insert(pos,m);
			}
			else if(ch=='D'){
				n--;
				scanf_(pos);
				splay.Delete(pos);
			}
			else if(ch=='R'){
				scanf_(pos);scanf_(m);
				splay.Replace(pos,m);
			}
			else if(ch=='Q'){
				scanf_(pos);scanf_(m);
				printf_(splay.Query(pos,m));
			}
		}
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值