codeforces gym-101736 Farmer Faul 平衡树+并查集
生活随笔
收集整理的這篇文章主要介紹了
codeforces gym-101736 Farmer Faul 平衡树+并查集
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目
題目鏈接
題意
給出nn個整數,其中1≤n≤1061≤n≤106。
給出三種操作:
- GROW x y,表示給xx位置的數增加yy。
- MAGIC x,表示給所有的數增加xx。
- CUT x,表示把所有大于x的數切割到x,并輸出本次切割割了多少。
題解
乍一看,似乎沒有很符合這個題目情形的數據結構,我們需要把多種數據結構結合起來。
首先我們把所有的數值相同的元素都歸并到一起(采用并查集的方法),并在這一個集合中找出一個關鍵的點(并查集的根節點)扔到平衡樹里面去,平衡樹的第一關鍵字是該并查集所具有的值,第二關鍵字是該并查集的根節點。
在這個基礎下,GROW x y操作就相當于把x處的元素從它所在并查集中拆出來,拆成一個獨立的點,然后給這個點的值加y,再把修改后的元素放入起所在的并查集中去。
時間復雜度:O(log(n))O(log(n))
MAGIC x操作就直接記錄一個累加hh就好了,在查詢的時候用到。
時間復雜度:O(1)O(1)
CUT x操作就相當于在平衡樹中,找到所有的值大于等于x-h的并查集,計算好貢獻以后,把所有的這些找到的并查集合并成為一個并查集,并且該并查集的值為x-h。
時間復雜度:O(兩次CUT之間的操作數)O(兩次CUT之間的操作數)
復雜度計算如果不對,請評論告知我。
注意
代碼
#include <iostream> #include <cstdio> #include <set> #define pr(x) cout<<#x<<":"<<x<<endl #define int long long using namespace std; typedef pair<int,int> pii; const int maxn = 2e6; int pa[maxn],sz[maxn]; void init(){ for(int i = 1;i < maxn;++i) pa[i] = i,sz[i] = 1;} int find(int x){ return x == pa[x]?x:pa[x] = find(pa[x]);} void join(int x,int y){int px = find(x),py = find(y);if(px != py) { pa[px] = py; sz[py] += sz[px];} } set<pii> st; int id,ida[maxn],n,q,h,tmp,a[maxn]; char op[6]; void ins(int pid){auto it = st.lower_bound(make_pair(a[pid],0));if(it == st.end() || it->first != a[pid]) st.insert(make_pair(a[pid],pid));else join(pid,it->second); } int split(int pos){int pid = find(ida[pos]); if(sz[pid] == 1) st.erase(st.find(make_pair(a[pid],pid)));else {sz[pid] --;ida[pos] = ++id;a[id] = a[pid];}return pid; } main() {init();id = 0;scanf("%lld%lld",&n,&q);for(int i = 1;i <= n;++i) {scanf("%lld",&tmp);ida[i] = ++id;a[id] = tmp;ins(id);}while(q--){scanf("%s",op);if(*op == 'G'){int pos,x;scanf("%lld%lld",&pos,&x);int nid = split(pos);a[nid] += x;ins(nid);}else if(*op == 'M'){int x;scanf("%lld",&x);h += x;}else if(*op == 'C'){int x;scanf("%lld",&x);int ans = 0;auto it = st.lower_bound(make_pair(x-h,0));if(it == st.end()) {printf("0\n");continue;}pii p = make_pair(x-h,it->second);ans += (it->first+h-x)*sz[it->second];a[it->second] = x-h;int pid = it->second;it = st.erase(it);while(it != st.end()){ans += (it->first-x+h)*sz[it->second];join(it->second,pid);it = st.erase(it);}st.insert(p);printf("%lld\n",ans);}}return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的codeforces gym-101736 Farmer Faul 平衡树+并查集的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么查看外网IP地址和内网IP地址如何查
- 下一篇: codeforces gym-10173