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\n",lt.queryone(x)); }
	if (ch[0]=='F' && ch[1]=='2'){ RG int x=gi(); printf("%d\n",lt.queryheap(x)); }
	if (ch[0]=='F' && ch[1]=='3') printf("%d\n",*--st.find(inf)+cnt);
    }
    return;
}

int main(){
    File("bzoj2333");
    work();
    return 0;
}


發佈了49 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章