bzoj2333

2333333333333

题号厉害  此题必做。。。


据说是什么什么可并堆(没听说过orz


于是自己yy了一个用splay + 线段树的作法


线段树用来维护全局最大值

splay维护单点最大  连通块最大


作法。略。。



#include <cstdio>
#include <iostream>

using namespace std;

char s[2];

int n,q,u,v,All;

int x[300010],ma[300010],ch[300010][2],fa[300010],lz[300010],st[300010],tp;

int X[1200010],l[1200010],r[1200010];

int father[300010];

int read_int () {
	char c = getchar();
	int re = 0,f = 1;
	for(;c > '9' || c < '0';c = getchar())
		if(c == '-') f = -1;
	for(;c >= '0' && c <= '9';c = getchar())
		re = re * 10 + c - '0';
	return re * f;
}

int find (int u) {
	if(father[u] == u)
		return u;
	return father[u] = find(father[u]);
}

void build (int L,int R,int M) {
	l[M] = L;
	r[M] = R;
	if(L == R) {
		X[M] = x[L];
		return;
	}
	int mid = (L + R) >> 1;
	build(L,mid,M << 1);
	build(mid + 1,R,M << 1 | 1);
	X[M] = max(X[M << 1],X[M << 1 | 1]);
}

void change (int pos,int M,int v) {
	if(l[M] == r[M] && l[M] == pos) {
		X[M] = v;
		return;
	}
	int mid = (l[M] + r[M]) >> 1;
	if(pos > mid)
		change(pos,M << 1 | 1,v);
	else change(pos,M << 1,v);
	X[M] = max(X[M << 1],X[M << 1 | 1]);
}

void pu (int M) {
	ma[M] = x[M];
	ma[M] = max(ma[M],ma[ch[M][0]]);
	ma[M] = max(ma[M],ma[ch[M][1]]);
}

void add (int M,int v) {
	x[M] += v;
	ma[M] += v;
	lz[M] += v;
}

void pd (int M) {
	if(lz[M] == 0)
		return;
	if(ch[M][0])
		add(ch[M][0],lz[M]);
	if(ch[M][1])
		add(ch[M][1],lz[M]);
	lz[M] = 0;
}

void rot (int M,int d) {
	ch[fa[M]][d ^ 1] = ch[M][d];
	if(ch[M][d])
		fa[ch[M][d]] = fa[M];
	int t = fa[fa[M]];
	fa[fa[M]] = M;
	ch[M][d] = fa[M];
	fa[M] = t;
	
	pu(ch[M][d]);
	pu(M);
	
	if(!t)
		return;
	if(ch[t][0] == ch[M][d])
		ch[t][0] = M;
	else ch[t][1] = M;
}

void splay (int M) {
	st[tp = 1] = M;
	int t = M;
	while(fa[t]) {
		t = fa[t];
		st[++tp] = t;
	}
	while(tp)
		pd(st[tp--]);
	
	while(fa[M]) {
		if(fa[fa[M]]) {
			int d = ch[fa[fa[M]]][0] == fa[M];
			if(ch[fa[M]][d] == M) {
				rot(M,d ^ 1);
				rot(M,d);
			}
			else {
				rot(M,d);
				rot(M,d);
			}
		}
		else {
			if(ch[fa[M]][0] == M)
				rot(M,1);
			else rot(M,0);
		}
	}
}

int main () {
	ma[0] = -0x3f3f3f3f;
	n = read_int();
	
	for(int i = 1;i <= n;++i) {
		ma[i] = x[i] = read_int();
		father[i] = i;
	}
	build(1,n,1);
		
	q = read_int();
	for(int i = 1;i <= q;++i) {
		scanf("%s",s);
		if(s[0] == 'U') {
			u = read_int();
			v = read_int();
			if(find(u) != find(v)) {
				change(find(u),1,-0x3f3f3f3f);
				father[find(u)] = find(v);
				splay(u);
				splay(v);
				int t = u;
				while(ch[t][0])
					t = ch[t][0];
				splay(t);
				fa[v] = t;
				ch[t][0] = v;
				pu(t);
				change(find(v),1,ma[t]);
			}
		}
		else {
			if(s[0] == 'A') {
				if(s[1] == '3')
					All += read_int();
				else {
					u = read_int();
					v = read_int();
					if(s[1] == '1') {
						splay(u);
						x[u] += v;
						int t = ma[u];
						pu(u);
						if(t != ma[u])
							change(find(u),1,ma[u]);
					}
					else {
						splay(u);
						add(u,v);
						change(find(u),1,ma[u]);
					}
				}
			}
			else {
				if(s[1] == '3')
					printf("%d\n",X[1] + All);
				else {
					u = read_int();
					splay(u);
					if(s[1] == '1')
						printf("%d\n",x[u] + All);
					else printf("%d\n",ma[u] + All);
				}
			}
		}
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值