刷題總結 棘手的操作(bzoj2333)

2022-05-23 13:18:11 字數 3750 閱讀 6354

scoi2011 day2 t1

有 n 個節點,標號從 1 到 n ,這 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:        輸出所有節點中,權值最大的節點的權值

輸入的第一行是乙個整數 n ,代表節點個數。

接下來一行輸入 n 個整數,a[1], a[2], …, a[n],代表 n 個節點的初始權值。

再下一行輸入乙個整數 q ,代表接下來的運算元。

最後輸入 q 行,每行的格式如題目描述所示。

對於操作 f1, f2, f3,輸出對應的結果,每個結果佔一行。

輸入  [複製]

0 0 0 

8 a1 3 -20 

a1 2 20 

u 1 3 

a2 1 10 

f1 3 

f2 3 

a3 -10 

f3

輸出

-10 

10 10

【資料範圍】

對於 30% 的資料,保證 n<=100,q<=10000

對於 80% 的資料,保證 n<=100000,q<=100000

對於 100% 的資料,保證 n<=300000,q<=300000

對於所有的資料,保證輸入合法,並且 -1000<=v, a[1], a[2], …, a[n]<=1000

這道題可以用可並堆或者線段樹來寫····

然而如果用可並堆得話得會刪除特定的點的操作··然而··我一直認為如果有刪除特定的點的操作還不如用splay···

然後我就打了2個小時的splay····最後寫不出來棄療了·····這道題用可並堆做出來的人是真正的勇士·····

也從這道題中發現了自己**能力的不足··一是粗心大意···二是不懂得簡化**··搞得寫到最後腦袋發蒙·····以後多看看那些寫得簡潔的人的**····

然後我就用線段樹來寫了··下面將線段樹的方法:

其實用線段樹寫的話最重要的是要維護乙個dfs序···在我們進行離線操作後dfs出來的dfs序必須保證:任意時間所有在同乙個並查集裡的點的dfs序是連續的···

怎麼做到呢?有兩點:

第一點:我們離線時侯的建邊的順序必須是和我們在離線後dfs時的順序是一致的

打個比方···題目中先是連1,2的邊··後連1,3的邊··那麼我們在dfs時候必須先走1,2的邊····

要做到這一點很簡單··考慮到臨接表加邊的順序與dfs時的順序是反的···因此我們每次不直接加邊··先將邊儲存起來···最後將所有邊倒著加入即可······

第二點:dfs順序必須和加邊的順序一致

依然舉上面的例子···如果我們連了2,1的邊···那麼我們必須保證先dfs2這個點,但如果按正常順序dfs,我們會先列舉到1這個點,如果1在連了21之後與其他點連了邊··直接dfs就會發生錯誤····

所以我們可以將1打個標記···在列舉到1的時候直接略過它··這樣就可以保證會先dfs到2,再dfs到1···與1相連的其他點也會被dfs到····換句話說··如果連了一條邊ab,我們要給b打乙個標記····保證dfs時先dfs到點a,再dfs到點b

解決了dfs序的順序後接下來就是線段樹的基礎操作了

#include#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int n=3e5+5

;const

int inf=0x3f3f3f3f

;struct

node

q[n];

struct

node1

e[n];

int dfn[n],last[n],tree[n*5],father[n],tag[n*5

],n,m,num[n],val[n],fst[n],go[n],nxt[n],tot,to,cnt,tol,pre[n];

bool

jud[n];

inline

void comb(int a,int

b)inline

int getfa(int

u)inline

intr()

inline

void dfs(int

u)inline

void add(int k,int

v)inline

void pushdown(intk)}

inline

void build(int k,int l,int

r)

int mid=(l+r)/2

; build(k*2,l,mid);build(k*2+1,mid+1

,r);

tree[k]=max(tree[k*2],tree[k*2+1

]);

return;}

inline

void modify(int k,int l,int r,int x,int y,int

v)

int mid=(l+r)/2

; pushdown(k);

if(x<=mid) modify(k*2

,l,mid,x,y,v);

if(y>mid) modify(k*2+1,mid+1

,r,x,y,v);

tree[k]=max(tree[k*2],tree[k*2+1

]);}

inline

int query(int k,int l,int r,int x,int

y)int

main()

else

if(s[0]=='a'

)

else

if(s[0]=='f'

)

} for(int i=tol;i;i--) comb(e[i].from

,e[i].to);

for(int i=1;i<=n;i++)

for(int i=1;i<=n;i++) pre[i]=dfn[i],val[dfn[i]]=num[i];build(1,1

,n);

for(int i=1;i<=m;i++)

if(q[i].op==2

)

if(q[i].op==3

)

if(q[i].op==4

)

if(q[i].op==5

)

if(q[i].op==6

)

if(q[i].op==7

) printf(

"%d\n

",query(1,1,n,1

,n));

} return0;

}

刷題總結 作詩(bzoj2821)

神犇sjy虐完heoi之後給傻 lyd出了一題 shy是t國的公主,平時的一大愛好是作詩。由於時間緊迫,shy作完詩 些漢字構成詩。因為shy喜歡對偶,所以shy規定最後選出的每個漢字都必須在 l,r 裡出現了正偶數次。而且shy認 為選出的漢字的種類數 兩個一樣的漢字稱為同一種 越多越好 為了拿到...

刷題總結 書架(bzoj1861)

小t有乙個很大的書櫃。這個書櫃的構造有些獨特,即書櫃裡的書是從上至下堆放成一列。她用1到n的正整數給每本書都編了號。小t在看書的時候,每次取出一本書,看完後放回書櫃然後再拿下一本。由於這些書太有吸引力了,所以她看完後常常會忘記原來是放在書櫃的什麼位置。不過小t的記憶力是非常好的,所以每次放書的時候至...

關於刷題入門 簡單題操作 的總結

一 判斷乙個數的奇偶性 判斷奇偶性 只需要對2取模即可,模為1位奇數,反之為偶 int a if a 2 1 else 二 判斷閏年 1 能整除4且不能整除100 2 能整除400 二者成立乙個即可 int y if y 400 0 y 4 0 y 100 0 else 三 判斷三邊是否能夠構成乙個...