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,輸出對應的結果,每個結果佔一行。
輸入 [複製]
3輸出0 0 0
8 a1 3 -20
a1 2 20
u 1 3
a2 1 10
f1 3
f2 3
a3 -10
f3
-1010 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 三 判斷三邊是否能夠構成乙個...