首页 > 代码库 > [bzoj 2333] 棘手的操作[SCOI2011]

[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\n",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\n",h1.v[x]+all);
 91 }
 92 il void F3(){
 93     printf("%d\n",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 }

 

[bzoj 2333] 棘手的操作[SCOI2011]