POJ3468--Splay维护区间加标记

好久没写Splay了。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=100005;
struct Splay_Tree{
	ll sum[maxn];
	int fa[maxn],ch[maxn][2],sz[maxn],val[maxn],add[maxn];
	void push_up(int p){
		sum[p]=val[p]+sum[ch[p][0]]+sum[ch[p][1]];
		sz[p]=1+sz[ch[p][0]]+sz[ch[p][1]];
	}
	void push_down(int p){
		if(add[p]){
			int u=ch[p][0],v=ch[p][1];
			if(u){
				val[u]+=add[p];
				add[u]+=add[p];
				sum[u]+=1ll*sz[u]*add[p];
			}if(v){
				val[v]+=add[p];
				add[v]+=add[p];
				sum[v]+=1ll*sz[v]*add[p];
			}add[p]=0;
		}
	}
	void push(int p){
		if(fa[p])push(fa[p]);
		push_down(p);
	}
	void rotate(int u,int p,bool k){
		if(fa[p])ch[fa[p]][p==ch[fa[p]][1]]=u;
		if(ch[u][k^1])fa[ch[u][k^1]]=p;
		fa[u]=fa[p],fa[p]=u;
		ch[p][k]=ch[u][k^1],ch[u][k^1]=p;
		push_up(p);
	}
	void splay(int u,int p){
		if(u==p)return;
		push(u);
		while(fa[u]!=p)
			rotate(u,fa[u],u==ch[fa[u]][1]);
		push_up(u);
	}
	ll query(int u,int v){
		splay(u-1,0),splay(v+1,u-1);
		return sum[ch[v+1][0]];
	}
	void update(int u,int v,int w){
		splay(u-1,0),splay(v+1,u-1);
		val[ch[v+1][0]]+=w,add[ch[v+1][0]]+=w;
		sum[ch[v+1][0]]+=1ll*sz[ch[v+1][0]]*w;
	}
}T;
int main(){
	char ch[10];
	int n,m,l,r,c;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n+1;i++){
		if(i<=n)scanf("%d",&T.val[i]);
		if(i>1)T.fa[i]=i-1,T.ch[i-1][1]=i;
	}
	while(m--){
		scanf("%s%d%d",ch,&l,&r);
		if(ch[0]=='Q')printf("%lld\n",T.query(l,r));
		else scanf("%d",&c),T.update(l,r,c);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值