zoukankan      html  css  js  c++  java
  • [模拟赛]棘手的操作


    这道题是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;
    }


  • 相关阅读:
    用grunt搭建自动化的web前端开发环境-完整教程
    SQL Server:触发器详解
    利用junit对springMVC的Controller进行测试
    jquery-barcode:js实现的条码打印
    16个良好的 Bootstrap Angularjs 管理后台主题
    Spring Security 4 Hello World Annotation+XML
    intellij 13新建javaweb项目并用tomcat 7启动
    JavaScript类和继承:constructor属性
    javascript 的面相对象
    javascript call apply bind caller callee 的用法
  • 原文地址:https://www.cnblogs.com/dcoi-king/p/5353664.html
Copyright © 2011-2022 走看看