日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

codeforces gym-101736 Farmer Faul 平衡树+并查集

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 codeforces gym-101736 Farmer Faul 平衡树+并查集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目

題目鏈接

題意

給出nn個整數,其中1n1061≤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之間的操作數)

復雜度計算如果不對,請評論告知我。

注意

  • 在這道題中并查集還應該記錄一個屬性,就是并查集的大小。
  • 該并查集支持元素從并查集中剝離,因此需要為每個元素設置一個盒子,即idaida數組,當一個元素被剝離的時候,給元素一個新的盒子,原來的并查集結構保持不變,但是要求原來并查集的大小-1。
  • 代碼

    #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 平衡树+并查集的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。