https://www.luogu.com.cn/problem/P3369
随机大法好啊啊啊
插入数字的时候,把平衡树按x分裂,插入x后再合并,具体可以看代码
#include<iostream> #include<algorithm> #include<cstdio> #include<ctime> #include<stack> using namespace std; const int maxn = 2e6+10; struct Node{ int l,r; int val,key; int siz; }tree[maxn]; int l,r,cnt,p,x,n; void update(int node){ tree[node].siz = tree[tree[node].l].siz + tree[tree[node].r].siz + 1; } void split(int node,int x,int& l,int& r){//node分裂成l和r,l--val<= x r--val > x if(node == 0){ l = r = 0; return ; } if(tree[node].val <= x){//左边部分 l = node; //左边儿子改了,继续分右边 split(tree[node].r,x,tree[node].r,r); } else{ r = node; split(tree[node].l,x,l,tree[node].l); } update(node); } int add(int val){ cnt++; tree[cnt].siz = 1; tree[cnt].l = tree[cnt].r = 0; tree[cnt].val = val; tree[cnt].key = rand(); } int merge(int l,int r){ if(!l || !r) return l + r;//总有一个是叶子 if(tree[l].key <= tree[r].key){//l做父亲 ,r比l大,所以r接上l的右子树 tree[l].r = merge(tree[l].r,r); update(l); return l; } else{ tree[r].l = merge(l,tree[r].l); update(r); return r; } } int kth(int node,int k){//排名第k的数字 if(k <= tree[tree[node].l].siz){ return kth(tree[node].l,k); } else if(tree[tree[node].l].siz + 1 == k){ return node; } else{ k -= tree[tree[node].l].siz + 1; return kth(tree[node].r,k); } } //int kth(int u,int k) //{//求排名第k的数 // if(k<=tree[tree[u].l].siz)//在左区间 // return kth(tree[u].l,k); // else if(k==tree[tree[u].l].siz+1)//这个数为此区间的根 // return u; // else // { // k-=(tree[tree[u].l].siz+1);//排名为k要减少左儿子的节点数 // return kth(tree[u].r,k);//在右区间 // } //} int main(){ int n; scanf("%d",&n); int root = 0; int p; srand((unsigned)time(NULL)); while(n--){ int op,x; scanf("%d %d",&op,&x); if(op == 1){ split(root,x,l,r);// node分裂成l和r,l--val<= x r--val > x add(x); root = merge(merge(l,cnt),r); } else if(op == 2){//删除x split(root,x,l,r); split(l,x-1,l,p); p = merge(tree[p].l,tree[p].r);//可能有多个x root = merge(merge(l,p),r); } else if(op == 3){//查询x的排名 split(root,x-1,l,r); printf("%d\n",tree[l].siz+1);//小于x的个数 root = merge(l,r); } else if(op == 4){//排名为x的数,记录重复 printf("%d\n",tree[kth(root,x)].val); } else if(op == 5){ split(root,x-1,l,r); printf("%d\n",tree[kth(l,tree[l].siz)].val); root = merge(l,r); } else{ split(root,x,l,r); printf("%d\n",tree[kth(r,1)].val); root = merge(l,r); } } return 0; }