poj3468 A Simple Problem with Integers

本文介绍了一种使用Splay树解决线段树问题的方法。通过具体实现细节展示了如何利用Splay树进行区间更新和查询操作,并提供了一个完整的C++代码示例。

@_poj3468线段树

.........

线段树  我用splay作死、、、、、、、、、、、


#include <cstdio>
#include <cstring>
#define cle(a,b) memset(a,b,sizeof a)
#define LL long long
#define D 100010
LL x[D],ar[D],lazy[D];
int root = 1,fa[D],ch[D][2],sz[D];		//lazy i 表示 i 的子树 都要加上一个值 	sum 表示子树和 
char nu;
int n,q,u,v;
LL w;
//虚拟一个1号  n+2 号点
void push_down (int X) {
	if(!lazy[X])
		return;
	for(int i = 0;i <= 1;i++) {
		if(ch[X][i]) {
			lazy[ch[X][i]] += lazy[X];
			x[ch[X][i]] += lazy[X] * sz[ch[X][i]];
		}
	}
	lazy[X] = 0;
}
void build (int l,int r) {
	int mid = (l + r) / 2;	
	if(l != r) {
	
			if(l != mid) {
				build(l,mid - 1);
				ch[mid][0] = (l + mid - 1) / 2;
				fa[ch[mid][0]] = mid;
			}
			build(mid + 1,r);			
			ch[mid][1] = (mid + 1 + r) / 2;
			fa[ch[mid][1]] = mid;
			x[mid] = x[ch[mid][0]] + x[ch[mid][1]] + ar[mid - 1];
			sz[mid] = sz[ch[mid][0]] + sz[ch[mid][1]];
			if(mid != 1 && mid != n + 2)
				++sz[mid];
	}
	else {
		x[mid] = ar[mid - 1];
		if(mid != 1 && mid != n + 2)
			sz[mid] = 1;
	}
}
void rot (int X,int d) {
	push_down(fa[X]);
	push_down(X);
	LL temp = x[X];
	x[X] = x[fa[X]];
	x[fa[X]] -= temp;
	x[fa[X]] += x[ch[X][d]];
	temp = sz[X];
	sz[X] = sz[fa[X]];
	sz[fa[X]] -= temp;
	sz[fa[X]] += sz[ch[X][d]];
	temp = fa[fa[X]];
	ch[fa[X]][d ^ 1] = ch[X][d];
	if(ch[X][d])
		fa[ch[X][d]] = fa[X];
	ch[X][d] = fa[X];
	fa[fa[X]] = X;
	fa[X] = temp;
	if(ch[temp][d] == ch[X][d])
		ch[temp][d] = X;
	else ch[temp][d ^ 1] = X;
}
void splay (int X) {
	while(fa[X]) {
		if(fa[fa[X]]) {	//有爷爷 
			int kind = ch[fa[fa[X]]][0] == fa[X];
			if(ch[fa[X]][kind] == X) {
				rot(X,kind ^ 1);
				rot(X,kind);
			}
			else {
				rot(X,kind);
				rot(X,kind);
			}
		}
		else {
			if(ch[fa[X]][0] == X)
				rot(X,1);
			else rot(X,0);
		}
	}
	root = X;
}
int main () {
	scanf("%d%d",&n,&q);
	for(int i = 1;i <= n;i++)
		scanf("%lld",&ar[i]);
	root = (n + 1) / 2;
	build(1,n + 2);
	for(int i = 1;i <= q;i++) {
		scanf(" %c%d%d",&nu,&u,&v);
		splay(v + 2);
		splay(u);
		if(nu == 'C') {
			scanf("%lld",&w);
			x[ch[ch[root][1]][0]] += sz[ch[ch[root][1]][0]] * w;
			lazy[ch[ch[root][1]][0]] += w;
			x[ch[root][1]] += sz[ch[ch[root][1]][0]] * w;
			x[root] += sz[ch[ch[root][1]][0]] * w;
		}
		else {
			printf("%lld\n",x[ch[ch[root][1]][0]]);
		}
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值