LibreOJ 2956 「SHOI2013」发牌 发表于 2018.12.09 | 分类于 题解 | 18 这一看不是平衡树随便搞吗? 等等,n≤7×105! 不管。 勇敢一点。 直接上个平衡树维护序列,销牌就是把序列的一段前缀移到序列末尾。 还好 BZOJ 不卡常。 代码: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970#include <cstdio>#include <cstdlib>#define ls(p) tree[p].lson#define rs(p) tree[p].rsonusing namespace std;const int N = 7e5;int n;int p;struct node{ int val,rnd,sz; int lson,rson;} tree[N + 10];inline void up(int p){ tree[p].sz = tree[ls(p)].sz + 1 + tree[rs(p)].sz;}void split(int p,int k,int &x,int &y){ if(!p) { x = y = 0; return ; } if(tree[ls(p)].sz < k) x = p,split(rs(p),k - tree[ls(p)].sz - 1,rs(x),y); else y = p,split(ls(p),k,x,ls(p)); up(p);}int merge(int x,int y){ if(!x || !y) return x | y; if(tree[x].rnd < tree[y].rnd) { rs(x) = merge(rs(x),y); up(x); return x; } else { ls(y) = merge(x,ls(y)); up(y); return y; }}int min_elem(int p){ if(ls(p)) return min_elem(ls(p)); return p;}int main(){ srand(19260817); scanf("%d",&n); for(register int i = 1;i <= n;++i) tree[i].val = i,tree[i].rnd = rand(),tree[i].sz = 1,p = merge(p,i); int a,x,y; while(n--) { scanf("%d",&a); a %= tree[p].sz; split(p,a,x,y); p = merge(y,x); printf("%d\n",tree[min_elem(p)].val); split(p,1,x,p); }} 本文作者: Alpha1022 本文链接: https://www.alpha1022.me/articles/loj-2956.htm 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!