寒假训练2.9

好久没训练了今天手感都没了就打了一道题
但是还没有调节出来,而且还没有写完,题目有好多个要求明天继续写继续调试

//维护序列
#include<bits/stdc++.h>
using namespace std;
#define debug cout<<" debug: "
typedef long long ll;
const int N=4e6+40;
const int inf=1e9;//用于区分你的flag标志因为有可能全部都设置为0那样的话就不太好判断了 
struct node{
	int s[2],p,v,sz,g;
	ll ls,rs,sum,tsum;//表示的是最大的连续字串和 
	int flag,tag;
	void init(int p_,int v_,int c){
		p=p_,v=v_,sz=1,g=c;
		flag=inf,tsum=ls=rs=sum=v;
		tag=0;
	}
}t[N];
int root,idx=1,rt,w[N];//一个是需要的添加的序列的新的根一个是原本的根 

void push_up(int u){
	auto s=t[u].s;
	t[u].sz=t[s[0]].sz+t[s[1]].sz+1;
	t[u].sum=t[u].v+t[s[0]].sum+t[s[1]].sum;
	t[u].ls=max(t[s[0]].ls,max(t[s[0]].sum+t[u].v,t[s[0]].sum+t[u].v+t[s[1]].ls));
	t[u].rs=max(t[s[1]].rs,max(t[s[1]].sum+t[u].v,t[s[1]].sum+t[u].v+t[s[0]].rs));
	t[u].tsum=max(max((ll)t[u].v,t[u].v+t[s[0]].rs+t[s[1]].ls),max(t[u].v+t[s[1]].ls,t[u].v+t[s[0]].rs));//中间贯穿的部分 
	t[u].tsum=max(max(t[s[0]].tsum,t[s[1]].tsum),max(t[u].ls,t[u].rs));
}

void push_down(int u){
	if(t[u].flag<inf){
		auto s=t[u].s; 
		t[s[0]].v=t[s[1]].v=t[u].flag;
		t[s[0]].sum=(ll)t[s[0]].sz*t[s[0]].flag;
		t[s[1]].sum=(ll)t[s[1]].sz*t[s[1]].flag;
		if(t[u].flag>=0){
			t[s[0]].ls=t[s[0]].rs=t[s[0]].tsum=t[s[0]].sum;
			t[s[1]].ls=t[s[1]].rs=t[s[1]].tsum=t[s[1]].sum;
		}else {
			t[s[0]].ls=t[s[0]].rs=t[s[1]].ls=t[s[1]].rs=t[s[0]].tsum=t[s[1]].tsum=t[u].flag;
		}
		t[s[0]].flag=t[s[1]].flag=t[u].flag;
		t[u].flag=inf;//清除标志 
		if(t[u].tag){
			swap(t[u].s[0],t[u].s[1]);
			t[s[0]].tag^=1;
			if(t[s[0]].tag){
				swap(t[s[0]].ls,t[s[0]].rs);
			}
			t[s[1]].tag^=1;
			if(t[s[1]].tag){
				swap(t[s[1]].ls,t[s[1]].rs);
			}
			t[u].tag=0;
		}//需要进行一个交换 	
	}
}

void rotate(int x){
	int y=t[x].p,z=t[y].p;
	int k=(t[y].s[1]==x);
	t[z].s[t[z].s[1]==y]=x,t[x].p=z;
	t[y].s[k]=t[x].s[k^1],t[t[x].s[k^1]].p=y;
	t[x].s[k^1]=y,t[y].p=x;
	push_up(y),push_up(x);
}

void splay(int x,int k){
	while(t[x].p!=k){
		int y=t[x].p,z=t[y].p;
		if(z!=k){
			if((t[z].s[1]==y)^(t[y].s[1]==x)){
				rotate(x);
			}else rotate(y); 
		} 
		rotate(x);
	}
	if(!k){
		root=x;
	}
	if(k==1){
		rt=x;
	}
}

void insert(int k,int i){
	int u=root,p=0;
	while(u){
		p=u;
		t[u].sz++;
		t[u].sum+=k;//这个才是具体的权值需要在这里就把他给更新了 
		u=t[u].s[i>t[u].g];
	}	
	u=++idx;
	t[u].init(p,k,i);
	if(p){
		t[p].s[i>t[p].g]=u;
	}	
	splay(u,0);//作为根搞起来 
} 

int l,r;

void init(){
	t[rt=l=++idx].init(1,-inf,0);
	t[r=++idx].init(l,inf,0);
	t[l].s[1]=r;//这个也是一个关系 
	push_up(l);//记得需要进行传递啊 
}

void build(int n){
	for(int i=1;i<=n;i++){
		insert(w[i],i);
	}
} 


int get_k(int u,int k){
	push_down(u); 
	int l=t[u].s[0];
	if(t[l].sz>=k)	return get_k(l,k);
	if(t[l].sz+1==k)	return u;//返回的是你的编号
	return get_k(t[u].s[1],k-t[l].sz-1);//记得这里不需要sum的总和 
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	init();
	for(int i=1;i<=n;i++){
		scanf("%d",&w[i]);	
	}
	build(n);//建立完了之后的话 
	t[r].s[0]=root;
	t[root].p=r;
	push_up(r),push_up(l);//他变化了之后的话,l也是会变化的 
	char a[10];
	for(int i=1;i<=m;i++){
		int tot,x,l,r,y;
		scanf("%s",a);
		if(a[0]=='I'){
			scanf("%d%d",&x,&tot);
			for(int i=1;i<=tot;i++){
				scanf("%d",&w[i]);
			}
			root=0;
			t[root].s[0]=t[root].s[1]=0;//清零 
			build(tot);
			int l=get_k(rt,x+1),r=get_k(rt,x+2);
			splay(l,1),splay(r,l);//真实的树是以rt为1开始进行的 
			t[r].s[0]=root;
			t[root].p=r;
			push_up(r),push_up(l);//记得更新 
		}else if(a[0]=='D'){
			scanf("%d%d",&x,&tot);
			int l=get_k(rt,x),r=get_k(rt,x+tot+1);//这个的话是包括这个本身的点的啊 
			splay(l,1),splay(r,l);
			t[r].s[0]=0;
			push_up(r),push_up(l);
		}else if(a[2]=='K'){
			scanf("%d%d%d",&x,&tot,&y);
			int l=get_k(rt,x),r=get_k(rt,x+tot+1);
			splay(l,1),splay(r,l);
			//这个的话是需要进行的修改标志 
			auto g=t[r].s[0];
			t[g].v=t[g].flag=y;
			t[g].sum=(ll)t[g].sz*t[g].v;
			if(y>=0){
				t[g].ls=t[g].rs=t[g].tsum=t[g].sum;
			}else {
				t[g].ls=t[g].rs=t[g].tsum=y;
			}
			push_up(r),push_up(l);
		}else if(a[0]=='R'){
			scanf("%d%d",&x,&tot);
			int l=get_k(rt,x),r=get_k(rt,x+tot+1);
			splay(l,1),splay(r,l);
			auto g=t[r].s[0];
			t[g].tag^=1;
			swap(t[g].ls,t[g].rs);
			push_up(r),push_up(l);
		}//这个的话就是交换了啊 
		else if(a[0]=='G'){
			scanf("%d%d",&x,&tot);
			int l=get_k(rt,x),r=get_k(rt,x+tot+1);
			splay(l,1),splay(r,l);
			auto g=t[r].s[0];
			printf("%lld\n",t[g].sum);
		}//直接获得答案的话还是有点不太确定的啊
		else {
			ll res=t[rt].tsum;
			printf("%lld\n",(res>inf)?res-inf:res);
		} 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值