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

    2333: [SCOI2011]棘手的操作

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2538  Solved: 986
    [Submit][Status][Discuss]

    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

     

    支持合并操作,修改操作,可以用可并堆;

      这个既要维护图的最大值,又要维护全局的最大值,全局的最大值就是每个块的最大值,那么就可以把这些块的最大值抠出来放到这个堆中维护; h1为连通块的堆,h2为全局最大值的堆。

      在斜堆里增加几个操作:

    1.find(x) 找到x的祖先(堆顶),这个直接暴力跳;

    2.Down(x) 涉及到整块修改,lz数组,与线段树写法一样;

    3.del(x)  先下放,合并左右儿子,更新父子关系,返回新的堆顶;合并时特判,如果修改的是根,则要更新根的值;

    4.Sum(x) :由于祖先节点中的lazy没有全部下放,所以在查询的时候要统计祖先的lazy;直接暴力跳就行,大概深度为log(n)

    5.Newnode(x,v) .......=0;v[x]=vv; 新建节点,不用在操作里写很多特判;

    对于每个操作

      对于A1:单点修改  , 修改后会改变位置,先将x的祖先在h2中删除,在把xh1

    中删除,把值统计好后,再合并h1与当前点;在合并h2与此时堆中的最大值;

      对于A2:删除h2中的x所在根的这个节点;newnode后合并;对于h1lz一下;

      对于A3:直接设全局变量all

      对于F1 : 当前值 祖先ly + 全局all

      对于F2 : 祖先值 + 全局all

      对于 F3: printf(“%d”,h2.v[h2.rt]+all);

      1 #include<bits/stdc++.h>
      2 #define re register
      3 #define il inline
      4 #define rep(i,a,b) for(register int i=a;i<=b;++i)
      5 #define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
      6 using namespace std;
      7 const int N=300020;
      8 int all,n;
      9 struct M_heap{
     10     int l[N],r[N],v[N],lz[N],fa[N];
     11     int rt;
     12     il int find(int x){
     13         while(fa[x]&&fa[x]!=x) x=fa[x];
     14         return x;
     15     }
     16     il void newnode(int x,int vv){
     17         fa[x]=l[x]=r[x]=v[x]=lz[x]=0;
     18         v[x]=vv;
     19     }
     20     il int sum(int x){
     21         re int res=0;
     22         while(fa[x]) res+=lz[fa[x]],x=fa[x];
     23         return res;
     24     }
     25     il void down(int x){
     26         v[l[x]]+=lz[x],v[r[x]]+=lz[x];
     27         lz[l[x]]+=lz[x],lz[r[x]]+=lz[x];
     28         lz[x]=0;
     29     }
     30     il int merge(int x,int y){
     31         if(x==0||y==0) return x+y;
     32         if(v[x]<v[y]) swap(x,y);
     33         down(x);
     34         r[x]=merge(r[x],y);
     35         fa[r[x]]=x;
     36         swap(l[x],r[x]);
     37         return x;
     38     }
     39     il int del(int x){
     40         down(x);
     41         int y=merge(l[x],r[x]);
     42         fa[y]=fa[x];// bug
     43         if(rt==x) rt=y;
     44         if(x==l[fa[x]]) l[fa[x]]=y;
     45         else r[fa[x]]=y;
     46         return find(y);
     47     }
     48 };
     49 M_heap h1,h2;
     50 inline int gi() {
     51     re int res=0,f=1;re char ch=getchar();
     52     while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
     53     if(ch=='-') f=-1,ch=getchar();
     54     while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar();
     55     return res*f;
     56 }
     57 il void U(){
     58     re int x=gi(),y=gi();
     59     x=h1.find(x),y=h1.find(y);
     60     if(x==y) return;
     61     if(h1.merge(x,y)==x) h2.del(y);
     62     else h2.del(x);
     63 }
     64 il void A1(){
     65     re int x=gi(),v=gi();
     66     h2.del(h1.find(x));
     67     int y=h1.del(x);
     68     h1.newnode(x,v+h1.v[x]+h1.sum(x));
     69     re int now=h1.merge(x,y);
     70     h2.newnode(now,h1.v[now]);
     71     h2.rt=h2.merge(h2.rt,now);
     72 }
     73 il void A2(){
     74     re int x=gi(),v=gi();
     75     x=h1.find(x);
     76     h1.v[x]+=v;h1.lz[x]+=v;
     77     h2.del(x);
     78     h2.newnode(x,h1.v[x]);
     79     h2.rt=h2.merge(h2.rt,x);
     80 }
     81 il void A3() {all+=gi();}
     82 il void F1(){
     83     re int x=gi();
     84     printf("%d
    ",h1.v[x]+h1.sum(x)+all);
     85     return;
     86 }
     87 il void F2(){
     88     re int x=gi();
     89     x=h1.find(x);
     90     printf("%d
    ",h1.v[x]+all);
     91 }
     92 il void F3(){
     93     printf("%d
    ",h2.v[h2.rt]+all);
     94     return;
     95 }
     96 int main(){
     97     file("heap");
     98     n=gi();
     99     re int u;
    100     rep(i,1,n){
    101         u=gi();h1.v[i]=h2.v[i]=u;
    102     }
    103     h2.rt=1;
    104     for(re int i=2;i<=n;i++) h2.rt=h2.merge(h2.rt,i);
    105     re int Q=gi(); char ch[4];
    106     while(Q--){
    107         scanf("%s",ch);
    108         if(ch[0]=='U') U();
    109         else if(ch[0]=='A'){
    110             if(ch[1]=='1') A1();
    111             else if(ch[1]=='2') A2();
    112             else A3();
    113         }
    114         else{
    115             if(ch[1]=='1') F1();
    116             else if(ch[1]=='2') F2();
    117             else F3();
    118         }
    119     }
    120     return 0;
    121 }
  • 相关阅读:
    day12. 闭包
    day11.函数的全局变量和局部变量
    day10.函数基础及函数参数
    day9.关于文件的操作
    day7.关于字符串的相关操作
    day8.列表、字典、集合相关操作
    day6. while双项循环及for循环
    LeetCode-Unique Binary Search Trees II
    LeetCode-Unique Binary Search Trees
    LeetCode-Edit Distance
  • 原文地址:https://www.cnblogs.com/ypz999/p/7230946.html
Copyright © 2011-2022 走看看