[模拟赛]棘手的操作


这道题是HugeGun出的一道题(据说是他改编的,bzoj2333) 但原题很毒瘤啊,有负数,他说正解是堆套堆Orz。

作为什么也不会的蒟蒻,看到这个瞬间想到带权冰茶集(点权)。。。 (汪神说他写的是火茶集2333)

一开始开一个数组,表示这个点和他的子孙将要被加上的值(因为觉得像lazy思想,所以起名lazy)

对于修改所有结点,可以用一个变量来存取,输出时加上即可,对于修改单点,直接加在那个点上更新下当前所在集合的最大值,

对于修改集合,将值加在点所在集合的代表元的lazy上就行了。。。

合并两个集合时,假设这两个集合的代表元为x,y,那么lazy[x] 应减去 Lazy[y] 。 因为显然现在lazy[y]中的数跟x所在集合没有半毛钱关系,而x集合中的点在合并后会加上lazy[y],所以应在lazy[x]中减去lazy[y]....

That is all 。。。。。


#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
const int N = 1e6+7;
int n,Q,f[N];
char lz[10];
int w[N],laz[N],pre,all,maxl[N],suf; //马克思 
int stk[N],top;

int find (int x) {
	if(f[f[x]] == f[x]) return f[x];
	int ret = x;
	top = 0;
	while(f[ret] != ret) stk[++top] = ret,ret = f[ret];
	for(int i=top-1;i;--i) laz[stk[i]] += laz[stk[i+1]] , f[stk[i]] = ret;
	return ret;
}

void merge (int x,int y) {
	int l = find (x), r = find (y);
	if(l == r) return ;
	maxl[r] = std :: max (maxl[r],maxl[l]);
	f[l] = r;
	laz[l] -= laz[r];
}

int main () {
	freopen("operation.in","r",stdin);
	freopen("operation.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&w[i]) ,maxl[i] = w[i], f[i] = i, suf = std :: max(suf,w[i]);
	scanf("%d",&Q);
	while(Q--) {
		scanf("%s",lz);
		if(lz[0] == 'U') {
			int x,y;
			scanf("%d%d",&x,&y);
			merge((x+pre)%n+1,(y+pre)%n+1);
		} else if(lz[0] == 'A') {
			int x,y;
			scanf("%d",&x);
			if(lz[1] == '3') all += x;
			else {
				scanf("%d",&y);
				x = (x + pre) % n + 1;
				int q = find(x);
				if(lz[1] == '1') w[x] += y,maxl[q] = std :: max(maxl[q],w[x] + laz[x] + (x == q ? 0 : laz[q])) , suf = std :: max(maxl[q],suf);
				else laz[q] += y , maxl[q] += y, suf = std :: max(suf,maxl[q]);
			}
		} else if(lz[0] == 'F') {
			if(lz[1] == '3') {
				printf("%d
",pre = suf + all);
				continue;
			}
			int x;
			scanf("%d",&x); x = (x+pre)%n+1;
			int q = find (x);
			if(lz[1] == '1') {
				int an = w[x];
				an += laz[x] + (x == q ? 0 : laz[q]);
				printf("%d
",pre = an + all);
			} else printf("%d
",pre = maxl[q] + all);
		}
	}
	//for(;;);
	return 0;
}


原文地址:https://www.cnblogs.com/dcoi-king/p/5353664.html