CF1418D Trash Problem(雙平衡樹維護)


題意:

Vova決定打掃房間。可以將房間表示為坐標軸OX。房間里有n堆垃圾,第i堆的坐標是整數pi。所有樁具有不同的坐標。

讓我們將總清理定義為以下過程。此過程的目標是在不超過兩個不同的x坐標下收集所有樁。為了實現此目標,Vova可以執行幾次(可能為零)移動。在移動期間,他可以選擇一些x,並使用掃帚將所有堆從x移動到x + 1或x-1。請注意,他無法選擇要移動多少個樁。

此外,有兩種查詢類型:

0 x-從坐標x移除一堆垃圾。確保此時在坐標x中有一個樁。
1 x-將一堆垃圾添加到坐標x。可以確保此時在坐標x中沒有樁。
請注意,有時房間中的垃圾堆為零。

Vova如果想在進行任何查詢之前進行徹底清理,則想知道他可以花費的最少移動次數。他還想在應用每個查詢后知道此移動次數。查詢以給定順序應用。請注意,總清理實際上並沒有發生,也不會改變堆的狀態。它僅用於計算移動次數。

為了更好地理解,請閱讀下面的“注釋”部分以查看第一個示例的說明。

輸入項
輸入的第一行包含兩個整數n和q(1≤n,q≤105)-分別是所有查詢之前的房間中的樁數和查詢數。

輸入的第二行包含n個不同的整數p1,p2,…,pn(1≤pi≤109),其中pi是第i堆的坐標。

接下來的q行描述查詢。第i個查詢用兩個整數ti和xi(0≤ti≤1;1≤xi≤109)描述,其中,如果需要從坐標xi中刪除樁,則ti為0;如果需要添加,則為1。坐標xi的一堆。保證對於ti = 0,在當前樁組中有這樣的樁,對於ti = 1,在當前樁組中沒有這樣的樁。

輸出量
打印q + 1個整數:在第一個查詢之前和q個查詢中的每個查詢之后,Vova進行總清理的最小移動次數。

題解:

大概意思就是支持插入和刪除,每次詢問集合里最大數和最小數的差減去最大的相鄰數的差。

開兩顆平衡樹,分別維護數值本身和差值。比賽時寫出了很多bug沒改出來。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
const int inf=2e9;
int a[maxn];
struct Treap_tree {
    int ch[2];
    int v;
    int dat;//優先級 
    int size;//子樹節點數 
    int cnt;//重復數 
}t[maxn];
int tot;
int root;
int newNode (int v) {
    tot++;
    t[tot].v=v;
    t[tot].dat=rand();//隨機優先級
    t[tot].size=1;
    t[tot].cnt=1;
    t[tot].ch[0]=0;
    t[tot].ch[1]=0;
    return tot; 
} 
void pushup (int x) {
    t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
void build () {
    root=newNode(-inf);
    t[root].ch[1]=newNode(inf);
    pushup(root);
}
void rotate (int &id,int d) {
    int tt=t[id].ch[d^1];
    t[id].ch[d^1]=t[tt].ch[d];
    t[tt].ch[d]=id;
    id=tt;
    pushup(t[id].ch[d]);
    pushup(id);
}
void ins (int &id,int v) {
    if (!id) {
        id=newNode(v);
        return;
    }
    if (v==t[id].v) t[id].cnt++;
    else {
        ins(t[id].ch[v>t[id].v],v);
        if (t[id].dat<t[t[id].ch[v>t[id].v]].dat) rotate(id,v<t[id].v);
    }
    pushup(id);
}
void remove (int &id,int v) {
    if (!id) return;
    if (v==t[id].v) {
        if (t[id].cnt>1) {
            t[id].cnt--;
            pushup(id);
            return;
        }
        if (t[id].ch[0]||t[id].ch[1]) {
            if (!t[id].ch[1]||t[t[id].ch[0]].dat>t[t[id].ch[1]].dat) {
                rotate(id,1);
                remove(t[id].ch[1],v);
            }
            else {
                rotate(id,0);
                remove(t[id].ch[0],v);
            }
            pushup(id);
        }
        else
            id=0;
        return;
    }
    remove(t[id].ch[v>t[id].v],v);
    pushup(id);
}
int rk (int id,int v) {
    if (!id) return 0;
    if (v==t[id].v) 
        return t[t[id].ch[0]].size+1;
    else if (v<t[id].v)
        return rk(t[id].ch[0],v);
    else
        return t[t[id].ch[0]].size+t[id].cnt+rk(t[id].ch[1],v);
}
int kth (int id,int k) {
    if (!id) return inf;
    if (k<=t[t[id].ch[0]].size)
        return kth(t[id].ch[0],k);
    else if (k<=t[t[id].ch[0]].size+t[id].cnt)
        return t[id].v;
    else
        return kth(t[id].ch[1],k-t[t[id].ch[0]].size-t[id].cnt);
}
int get_pre (int id,int v) {
    int pre;
    while (id) {
        if (t[id].v<v)
            pre=t[id].v,id=t[id].ch[1];
        else
            id=t[id].ch[0];
    }
    return pre;
}
int get_next (int id,int v) {
    int nxt;
    while (id) {
        if (t[id].v>v)
            nxt=t[id].v,id=t[id].ch[0];
        else
            id=t[id].ch[1];
    }
    return nxt;
}
int get_max (int id) {
    int Max=0;
    while (t[id].ch[1]) {
        if (t[id].v!=inf&&t[id].v!=-inf)
            Max=max(Max,t[id].v);
        id=t[id].ch[1]; 
    }
    if (t[id].v!=inf&&t[id].v!=-inf)
        Max=max(Max,t[id].v);
    return Max;
}
int get_min (int id) {
    int Min=inf;
    while (t[id].ch[0]) {
        if (t[id].v!=inf&&t[id].v!=-inf)
            Min=min(Min,t[id].v);
        id=t[id].ch[0]; 
    }
    if (t[id].v!=inf&&t[id].v!=-inf)
        Min=min(Min,t[id].v);
    return Min;
}
map<int,int> mp;
set<int> st,wjm;
int main () {
    int n,q;
    scanf("%d%d",&n,&q);
    build();
    for (int i=1;i<=n;i++) scanf("%d",a+i),ins(root,a[i]),wjm.insert(a[i]);
    int cnt=n;
    sort(a+1,a+n+1);
    for (int i=1;i<n;i++) {
        mp[a[i+1]-a[i]]++;
        st.insert(a[i+1]-a[i]);
    }
    int ans=a[n]-a[1];
    if (st.size())printf("%d\n",ans-*st.rbegin());
    else printf("%d\n",ans);
    while (q--) {
        int op;
        int x;
        int tt=0;
        scanf("%d%d",&op,&x);
        if (op==1) {
            wjm.insert(x);
            cnt++;
            ins(root,x);
            int nxt=get_next(root,x);
            int pre=get_pre(root,x);
            //printf("%d %d\n",nxt,pre);
            if (nxt!=inf&&pre!=-inf) {
                mp[nxt-pre]--;
                if (!mp[nxt-pre]) st.erase(nxt-pre);
                mp[x-pre]++;
                if (!st.count(x-pre)) st.insert(x-pre);
                mp[nxt-x]++;
                if (!st.count(nxt-x)) st.insert(nxt-x);
            }
            else if (nxt==inf&&pre!=-inf) {
                mp[x-pre]++;
                if (!st.count(x-pre)) st.insert(x-pre);
            }
            else if (pre==-inf&&nxt!=inf) {
                mp[nxt-x]++;
                if (!st.count(nxt-x)) st.insert(nxt-x);
            }
        }
        else {
            wjm.erase(x);
            cnt--;
            remove(root,x);
            int nxt=get_next(root,x);
            int pre=get_pre(root,x);
            //printf("%d %d\n",nxt,pre);
            if (nxt!=inf&&pre!=-inf) {
                mp[nxt-x]--;
                if (!mp[nxt-x]) st.erase(nxt-x);
                mp[x-pre]--;
                if (!mp[x-pre]) st.erase(x-pre);
                mp[nxt-pre]++; 
                if (!st.count(nxt-pre)) st.insert(nxt-pre);
            }
            else if (nxt==inf&&pre!=-inf) {
                mp[x-pre]--;
                if (!mp[x-pre]) st.erase(x-pre);
                
            }
            else if (pre==-inf&&nxt!=inf) {
                mp[nxt-x]--;
                if (!mp[nxt-x]) st.erase(nxt-x);
            }
        }
        if (cnt<=2||!st.size()) {
            printf("0\n");
            continue;
        }
        int r=*wjm.rbegin();
        int l=*wjm.begin();
        ans=r-l;
        //printf("%d %d\n",l,r);
        printf("%d\n",ans-*st.rbegin());
    } 
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM