1. 程式人生 > >[bzoj 2333] 棘手的操作[SCOI2011]

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

rip || gree discuss 最大的 efi open node blog

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

對於 F3printf(“%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]