有n個節點,標號從1到n,這n個節點一開始相互不連通。第i個節點的初始權值為a[i],接下來有如下一些操作:
輸入格式:
輸入的第一行是乙個整數n,代表節點個數。接下來一行輸入n個整數,a[1], a[2], ..., a[n],代表n個節點的初始權值。再下一行輸入乙個整數q,代表接下來的運算元。最後輸入q行,每行的格式如題目描述所示。
輸出格式:
對於操作f1, f2, f3,輸出對應的結果,每個結果佔一行。
輸入樣例#1:
3輸出樣例#1:0 0 0
8a1 3 -20
a1 2 20
u 1 3
a2 1 10
f1 3
f2 3
a3 -10
f3
-10對於30%的資料,保證 n<=100,q<=100001010
對於80%的資料,保證 n<=100000,q<=100000
對於100%的資料,保證 n<=300000,q<=300000
對於所有的資料,保證輸入合法,並且 -1000<=v, a[1], a[2], ..., a[n]<=1000
第一想法:lct
但是 lct 不能求出 x 所在聯通塊,更不能修改。
又看到了 求最大權值 ,於是想到了 左偏樹。
1.合併兩個堆:直接merge
2.把某個點加:把這個點刪了,再加乙個更新了權值之後的點。
3.整個堆加:在根上打mark
4.全域性加:記個全域性mark
5.查詢單點:一路加上所有父親的mark再輸出
6.查詢堆最大值:直接輸出
7.查詢全域性最大值:第七個操作需要把所有堆的根提取出來再建個堆。每次merge都要把並進去的堆刪掉,單點加和整堆加都需要更新最大值。
刪除操作:我們先和刪除最值一樣,把它的孩子合併起來。
因為我們合併後的新樹的距離可能會改變,所以要更新一下q的距離。
假如q的距離是p的距離+1,那麼無論p是左右子樹都不需要調整。
假如p的距離+1小於q的距離,就改下q的距離,而且假如p是左子樹的話需要交換子樹。由於q的距離小了,還需要更新它的父親。
假如p距離變大了的話,看看p是不是左子樹,是左子樹的話就結束了。但是p是右子樹的話,就有兩種可能,假如p的距離仍然小於q的左子樹,那就直接改q的距離就好了;大於的話還要換下子樹,向上走。(在這裡還有一種情況就是原來的左右子樹距離一樣,那就不用更新q的距離,直接結束就好了)
附**:
#include#include#include#include#define maxn 300010
using namespace std;
int n,m,addall=0,root;
struct treea[maxn];
inline void independent(int rt)
inline void pushdown(int rt)
if(a[rt].son[1])
a[rt].flag=0;
} int merge(int x,int y)
int find(int x)
int sum(int rt)
int deletemin(int rt)
return q.front();
}}one,two;
inline int read()
while(c>='0'&&c<='9')
return date*w;
}int main()
break;
}case 'a':
case '2':
case '3':addall+=x;break;
}break;
}case 'f':
case '2':
case '3':
}break;
}} }
return 0;
}
洛谷P3273 SCOI2011 棘手的操作
有n個節點,標號從1到n,這n個節點一開始相互不連通。第i個節點的初始權值為a i 接下來有如下一些操作 u x y 加一條邊,連線第x個節點和第y個節點a1 x v 將第x個節點的權值增加va2 x v 將第x個節點所在的連通塊的所有節點的權值都增加va3 v 將所有節點的權值都增加vf1 x 輸...
題解 洛谷P3275 SCOI2011 糖果
一道條件非常多的差分約束 把 a b 轉化為 a b le 1 就可做了 a b 的情況同理 若有負環則無解輸出 1 注意本題中要求每個人都有糖果 所以假設乙個源點 d 使 d d ge 1 1 le i le n 另外,本題要求得是最小值 x x le a 的形式求出的是最大值 要轉化成 x x ...
題解 洛谷P3275 SCOI2011 糖果
題面 其實是裸的差分約束吧 qwq。對於每一種情況分類討論一下 這裡說一下差分約束最基本的建圖方式 如何求最值呢?結論 如果求的是最小值,那麼我們就跑一遍最長路 否則就跑一遍最短路。具體的方法就是對於每乙個 x i geq c 的條件,建立乙個超級源點 0 由 0 向 x i 連一條長度為 c 的邊...