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

    2333: [SCOI2011]棘手的操作

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2537  Solved: 985
    [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

    2.SCOI2011棘手的操作

    完成时间:2017.7.23.21.35

    时耗:3h

    思路{

      题号有点小牛逼。。。。。。。。。

      看到合并,查询最大值,我们果断想到了可并堆。

      操作1:合并两个左偏树,找出两个节点所属的左偏树,合并即可

      操作2:给一特定节点的值增加v,我们可以先取出这个元素,修改它的值,合并。

      操作3:给一个左偏树的所有值增加一个数,像线段树那样打个标记都可以了。

      操作4;直接搞个全局变量记录all都可以辣。

      查询1:输出x节点的权值=当前的值加上跳父亲的lazy+全局all

      查询2:直接取堆顶元素即可。

      查询3:这个只要取各个堆的堆顶元素建一个堆,在各种操作中先删除,再单点修改,再插入。

    }

    //第一次写可并堆的数据结构火题,还是写下注释吧。。。。。。
    #include<bits/stdc++.h>
    #define RG register
    #define il inline 
    #define N 300010
    using namespace std;
    int l1[N],r1[N],d1[N],d2[N],v1[N],lazy[N],l2[N],r2[N],v2[N],f1[N],f2[N],rt,n,q,all;
    void down(int x){
      v1[l1[x]]+=lazy[x],v1[r1[x]]+=lazy[x];
      lazy[l1[x]]+=lazy[x],lazy[r1[x]]+=lazy[x];
      lazy[x]=0;
    }//下放懒标记。。
    int find1(int x){int X=x;while(f1[X])X=f1[X];return X;}//找霸霸
    int sum(int x){int sum=0,X=f1[x];while(X)sum+=lazy[X],X=f1[X];return sum;}//累加LAZY
    int merge1(int x,int y){//大根堆
      if(!x||!y)return x+y;
      if(v1[x]<v1[y])swap(x,y);
      down(x);r1[x]=merge1(r1[x],y);f1[r1[x]]=x;
      if(d1[r1[x]]>d1[l1[x]])swap(r1[x],l1[x]);
      d1[x]=d1[r1[x]]+1;return x;
    }
    int merge2(int x,int y){
      if(!x||!y)return x+y;
      if(v2[x]<v2[y])swap(x,y);
      r2[x]=merge2(r2[x],y);f2[r2[x]]=x;
      if(d2[r2[x]]>d2[l2[x]])swap(r2[x],l2[x]);
      d2[x]=d2[r2[x]]+1;return x;
    }
    int del1(int x){down(x);
      int le=l1[x],ri=r1[x];int y=merge1(le,ri);
      if(x==l1[f1[x]])l1[f1[x]]=y;else r1[f1[x]]=y;
      f1[y]=f1[x];return find1(y);
    }
    void del2(int x){
      int le=l2[x],ri=r2[x];int y=merge2(le,ri);
      if(rt==x)rt=y;
      if(x==l2[f2[x]])l2[f2[x]]=y;else r2[f2[x]]=y;
      f2[y]=f2[x];
    }
    void getnode1(int x,int v){f1[x]=d1[x]=l1[x]=r1[x]=0,v1[x]=v;}
    void getnode2(int x,int v){f2[x]=d2[x]=l2[x]=r2[x]=0,v2[x]=v;}
    void U(){
      int x,y;scanf("%d%d",&x,&y);
      x=find1(x),y=find1(y);
      if(x!=y){
        if(merge1(x,y)==x)del2(y);else del2(x);
      }
    }
    void A1(){
      int x,v;scanf("%d%d",&x,&v);
      del2(find1(x));//堆顶元素可能不是最优的了。。。。。
      int y=del1(x);
      getnode1(x,v+v1[x]+sum(x));
      int z=merge1(y,x);getnode2(z,v1[z]);
      rt=merge2(rt,z);
    }
    void A2(){
      int x,v;scanf("%d%d",&x,&v);
      x=find1(x);v1[x]+=v;lazy[x]+=v;
      del2(x);getnode2(x,v1[x]);rt=merge2(rt,x);
    }
    void A3(){int v;scanf("%d",&v);all+=v;}
    void F1(){int x;scanf("%d",&x);printf("%d
    ",v1[x]+sum(x)+all);}
    void F2(){int x;scanf("%d",&x);printf("%d
    ",v1[find1(x)]+all);}
    void F3(){printf("%d
    ",v2[rt]+all);}
    int main(){
      freopen("1.in","r",stdin);
      freopen("1.out","w",stdout);
      scanf("%d",&n);
      for(int i=1;i<=n;++i)scanf("%d",&v1[i]),v2[i]=v1[i];
      scanf("%d",&q);rt=1;for(int i=2;i<=n;++i)rt=merge2(rt,i);char ch[3];
      for(int i=1;i<=q;++i){
        scanf("%s",ch);
        if(ch[0]=='U')U();
        if(ch[0]=='A'){
          if(ch[1]=='1')A1();
          if(ch[1]=='2')A2();
          if(ch[1]=='3')A3();
        }
        if(ch[0]=='F'){
          if(ch[1]=='1')F1();
          if(ch[1]=='2')F2();
          if(ch[1]=='3')F3();
        }
      }return 0;
    }
    

      

  • 相关阅读:
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    Python for Data Science
    软件工程实践总结
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7226263.html
Copyright © 2011-2022 走看看