原题链接
思路:
使用权值树状数组.
插入操作先查找对应的位置值是不是 0, 然后插入.
删除操作二分查找最大值和最小值.
美丽值总和做个前缀和就行,至于总的价格在插入和删除的时候维护即可.
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| #include <cstdio> #include <cstdlib> typedef long long LL; const int Mn(1000050);
class BinT { private: int len; LL* c; inline int lb(int x) { return x&(-x); } public: explicit BinT(int n=Mn) { this->len = n; c = (LL*)malloc((n+1)*sizeof(LL)); } void add(int p,LL x) { while(p<=len) { c[p] += x; p += lb(p); } } LL sum(int p) { LL ret(0); while(p) { ret += c[p]; p -= lb(p); } return ret; } }bt;
int main() { int opt; LL prc(0); while(~scanf("%d",&opt)) { if(opt == -1) { break; } else if(opt == 1) { int x,y; scanf("%d %d",&x,&y); if(bt.sum(y)-bt.sum(y-1)==0) { bt.add(y,x); prc += y; } } else if(opt == 2) { if(bt.sum(Mn)==0) { continue; } int l(1),r(Mn); while(r-l>3) { int mid((l+r)/2); if(bt.sum(r)-bt.sum(mid)>0) { l = mid+1; } else { r = mid; } } for(int i(r);i>=l;--i) { LL tmp; if((tmp=bt.sum(i)-bt.sum(i-1))>0) { bt.add(i,-tmp); prc -= i; break; } } } else if(opt == 3) { if(bt.sum(Mn)==0) { continue; } int l(1),r(Mn); while(r-l>3) { int mid((l+r)/2); if(bt.sum(mid)==0) { l = mid+1; } else { r = mid; } } for(int i(l);i<=r;++i) { LL tmp; if((tmp=bt.sum(i)-bt.sum(i-1))>0) { bt.add(i,-tmp); prc -= i; break; } } } } printf("%lld %lld",bt.sum(Mn),prc); return 0; }
|