P2286寵物收養所(Splay)
阿新 • • 發佈:2021-12-07
傳送門:寵物收養所
可以考慮只維護一棵 Splay,隨時判斷寵物和領養者誰多,把多的插入到 Splay 裡,類似營業額統計,對於新加進來的少的求前驅後繼並比較誰更近。(注意判斷相等的特殊情況,處理按題面來)
然後累計到答案裡就可以啦。(reliese 操作刪除的是某個值而不是節點編號,只有我這個蒟蒻才會錯啦)
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 80000 + 10; const int mod = 1000000; int n,res,tot,root; int pet,cus; int opt[N],spe[N],val[N],fa[N],siz[N],cnt[N],ch[N][2]; int create(int v,int fs) { val[++tot] = v,fa[tot] = fs; ch[tot][0] = ch[tot][1] = 0; siz[tot] = cnt[tot] = 1; return tot; } void maintain(int x) { if(not x) return; siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x]; } int getwhich(int x) { return x == ch[fa[x]][1]; } void rotate(int x) { int ff = fa[x],gf = fa[ff]; int k = getwhich(x),tmp = ch[x][k^1]; fa[tmp] = ff,ch[ff][k] = tmp; fa[x] = gf; if(gf) ch[gf][getwhich(ff)] = x; fa[ff] = x,ch[x][k^1] = ff; maintain(x),maintain(ff); } void splay(int x) { for(int ff = fa[x];ff = fa[x];rotate(x)) if(fa[ff]) rotate(getwhich(ff) == getwhich(x) ? ff : x); root = x; } void ins(int v) { if(not root) { root = create(v,0); return ; } int cur = root,ff = 0; while(1) { if(val[cur] == v) { cnt[cur]++; maintain(cur),maintain(ff); splay(cur); break; } ff = cur; cur = ch[cur][val[cur] < v]; if(not cur) { ch[ff][val[ff] < v] = create(v,ff); maintain(ff); splay(tot); break; } } } int bargain(int k) { int cur = root; while(1) { if(k <= siz[ch[cur][0]]) cur = ch[cur][0]; else if(siz[ch[cur][0]] + cnt[cur] >= k) return val[cur]; else { k -= siz[ch[cur][0]] + cnt[cur]; cur = ch[cur][1]; } } } int rankle(int v) { int cur = root,ans = 0; while(1) { if(not cur) return ans + 1; if(v < val[cur]) cur = ch[cur][0]; else if(v == val[cur]) { ans += siz[ch[cur][0]]; splay(cur); return ans + 1; } else { ans += siz[ch[cur][0]] + cnt[cur]; cur = ch[cur][1]; } } } int charge() { int cur = ch[root][0]; while(ch[cur][1]) cur = ch[cur][1]; return cur; } int recoil() { int cur = ch[root][1]; while(ch[cur][0]) cur = ch[cur][0]; return cur; } void reliese(int v) { rankle(v); if(cnt[root] > 1) { cnt[root]--; maintain(root); return ; } else if(not ch[root][0] and not ch[root][1]) { root = 0; return ; } else if(not ch[root][0]) { root = ch[root][1]; fa[root] = 0; return ; } else if(not ch[root][1]) { root = ch[root][0]; fa[root] = 0; return ; } int tmp = ch[root][1],pre = charge(); splay(pre); fa[tmp] = root; ch[root][1] = tmp; maintain(root); } signed main() { scanf("%lld",&n); for(int i = 1;i <= n;i++) scanf("%lld%lld",&opt[i],&spe[i]); for(int i = 1;i <= n;i++) { if(pet == cus) ins(spe[i]); else if(pet < cus) { if(opt[i]) ins(spe[i]); else { ins(spe[i]); rankle(spe[i]); int pre = charge(),suf = recoil(); if(not pre) { res = (res + labs(spe[i] - val[suf])) % mod; reliese(val[suf]); } else if(not suf) { res += labs(spe[i] - val[pre]); res %= 1000000; reliese(val[pre]); } else { if(labs(spe[i] - val[pre]) <= labs(spe[i] - val[suf])) res += labs(spe[i] - val[pre]),res %= 1000000,reliese(val[pre]); else res += labs(spe[i] - val[suf]), res %= 1000000,reliese(val[suf]); } reliese(spe[i]); } } else { if(not opt[i]) ins(spe[i]); else { ins(spe[i]); rankle(spe[i]); int pre = charge(),suf = recoil(); if(not pre) { res += labs(spe[i] - val[suf]); res %= 1000000; reliese(val[suf]); } else if(not suf) { res += labs(spe[i] - val[pre]); res %= 1000000; reliese(val[pre]); } else { if(labs(spe[i] - val[pre]) <= labs(spe[i] - val[suf])) res += labs(spe[i] - val[pre]),res %= 1000000,reliese(val[pre]); else res += labs(spe[i] - val[suf]), res %= 1000000,reliese(val[suf]); } reliese(spe[i]); } } opt[i] ? cus++ : pet++; //cout << res << endl; } printf("%lld\n",res); return 0; }