題意:
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()); } }