zoukankan      html  css  js  c++  java
  • bzoj2333 [SCOI2011]棘手的操作

    Description

    N个节点,标号从1N,这N个节点一开始相互不连通。第i个节点的初始权值为a[i],接下来有如下一些操作:

    U x y: 加一条边,连接第x个节点和第y个节点

    A1 x v: 将第x个节点的权值增加v

    A2 x v: 将第x个节点所在的连通块的所有节点的权值都增加v

    A3 v: 将所有节点的权值都增加v

    F1 x: 输出第x个节点当前的权值

    F2 x: 输出第x个节点所在的连通块中,权值最大的节点的权值

    F3: 输出所有节点中,权值最大的节点的权值

    Input

    输入的第一行是一个整数N,代表节点个数。

    接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。

    再下一行输入一个整数Q,代表接下来的操作数。

    最后输入Q行,每行的格式如题目描述所示。

    Output

    对于操作F1, F2, F3,输出对应的结果,每个结果占一行。

    Sample Input

    3

    0 0 0

    8

    A1 3 -20

    A1 2 20

    U 1 3

    A2 1 10

    F1 3

    F2 3

    A3 -10

    F3

    Sample Output


    -10

    10

    10

    HINT



     对于30%的数据,保证 N<=100,Q<=10000


    对于80%的数据,保证 N<=100000,Q<=100000


    对于100%的数据,保证 N<=300000,Q<=300000


    对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], …, a[N]<=1000


    正解:可并堆

    这题我做了一上午,果真棘手。。

    使用左偏树维护每个集合,运用lazy标记下放。查询全局最大值就用multiset吧。


    //It is made by wfj_2048~
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define inf 1<<30
    #define il inline
    #define RG register
    #define ll long long
    #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    
    using namespace std;
    
    const int N=300010;
    
    multiset <int> st;
    
    int n,q,cnt;
    char ch[5];
    
    il int gi(){
        RG int x=0,q=0; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
        if (ch=='-') q=1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q ? -x : x;
    }
    
    il void insert(RG int x){ st.insert(x); return; }
    
    il void erase(RG int x){ st.erase(st.find(x)); return; }
    
    struct left_tree{
    
        int fa[N],ls[N],rs[N],dis[N],key[N],lazy[N],q[N],tot;
    
        il void build(RG int x,RG int k){
    	ls[x]=rs[x]=dis[x]=lazy[x]=fa[x]=0,key[x]=k; return;
        }
    
        il int father(RG int x){
    	while (fa[x]) x=fa[x]; return x;
        }
    
        il void pushdown(RG int x){
    	if (!lazy[x]) return;
    	if (ls[x]) key[ls[x]]+=lazy[x],lazy[ls[x]]+=lazy[x];
    	if (rs[x]) key[rs[x]]+=lazy[x],lazy[rs[x]]+=lazy[x];
    	lazy[x]=0; return;
        }
    
        il void finddown(RG int x){
    	while (x) q[++tot]=x,x=fa[x];
    	while (tot) pushdown(q[tot--]); return;
        }
    
        il int top(RG int x){ return key[father(x)]; }
    
        il int merge(RG int x,RG int y){
    	if (!x || !y) return x+y; if (key[x]<key[y]) swap(x,y);
    	pushdown(x),rs[x]=merge(rs[x],y),fa[rs[x]]=x;
    	if (dis[ls[x]]<dis[rs[x]]) swap(ls[x],rs[x]);
    	if (!rs[x]) dis[x]=0; else dis[x]=dis[rs[x]]+1; return x;
        }
    
        il int del(RG int x){
    	finddown(x); RG int q=fa[x],p=merge(ls[x],rs[x]); build(x,key[x]);
    	if (q && ls[q]==x) ls[q]=p; if (q && rs[q]==x) rs[q]=p; fa[p]=q;
    	while (q){
    	    if (dis[ls[q]]<dis[rs[q]]) swap(ls[q],rs[q]);
    	    if ((rs[q] && dis[rs[q]]+1==dis[q]) || (!rs[q] && !dis[q])) break;
    	    if (!rs[q]) dis[q]=0; else dis[q]=dis[rs[q]]+1; q=fa[q];
    	}
    	return father(p);
        }
    
        il void add(RG int x,RG int v){
    	finddown(x),erase(key[father(x)]);
    	key[x]+=v,insert(key[merge(x,del(x))]); return;
        }
    
        il void add_heap(RG int x,RG int v){
    	x=father(x),erase(key[x]);
    	key[x]+=v,lazy[x]+=v,insert(key[x]); return;
        }
    
        il void addedge(RG int x,RG int y){
    	x=father(x),y=father(y); if (x==y) return;
    	if (merge(x,y)==y) erase(key[x]);
    	else erase(key[y]); return;
        }
    
        il int queryone(RG int x){ finddown(x); return key[x]+cnt; }
    
        il int queryheap(RG int x){ return top(x)+cnt; }
    
    }lt;
    
    il void work(){
        n=gi(); for (RG int i=1;i<=n;++i){ RG int x=gi(); lt.build(i,x),insert(x); } q=gi();
        for (RG int i=1;i<=q;++i){
    	scanf("%s",ch); if (ch[0]=='U'){ RG int x=gi(),y=gi(); lt.addedge(x,y); }
    	if (ch[0]=='A' && ch[1]=='1'){ RG int x=gi(),v=gi(); lt.add(x,v); }
    	if (ch[0]=='A' && ch[1]=='2'){ RG int x=gi(),v=gi(); lt.add_heap(x,v); }
    	if (ch[0]=='A' && ch[1]=='3') cnt+=gi();
    	if (ch[0]=='F' && ch[1]=='1'){ RG int x=gi(); printf("%d
    ",lt.queryone(x)); }
    	if (ch[0]=='F' && ch[1]=='2'){ RG int x=gi(); printf("%d
    ",lt.queryheap(x)); }
    	if (ch[0]=='F' && ch[1]=='3') printf("%d
    ",*--st.find(inf)+cnt);
        }
        return;
    }
    
    int main(){
        File("bzoj2333");
        work();
        return 0;
    }
    


  • 相关阅读:
    【 Java框架】Spring的核心IOC源码分析
    小猪学设计模式——模板方法模式
    小猪学设计模式——工厂模式之抽象工厂
    小猪学设计模式——工厂模式之工厂方法模式
    小猪学设计模式——工厂模式之简单工厂(静态工厂)
    HTML5 Server-sent Events ASP.NET向Web客户端推送信息
    jquery.min.map 404 (Not Found)
    C# HTTP 断点续传
    C#操作JSON字符串
    Visual Studio 解决Windows Web服务框架中出现了无法识别的错误
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416598.html
Copyright © 2011-2022 走看看