P3380 二逼平衡树(带修改区间第K大+平衡树的基本操作)(线段树套Treap树)
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
-
查询k在区间内的排名
-
查询区间内排名为k的值
-
修改某一位值上的数值
-
查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)
-
查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+100; const int inf=2147483647; int n,m; int a[maxn]; struct Treap_tree { int ch[2]; int v; int dat;//优先级 int size;//子树节点数 int cnt;//重复数 }t[maxn*10]; 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; 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; 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) { if (!id) return -inf; if (t[id].v>=v) return get_pre(t[id].ch[0],v); else return max(t[id].v,get_pre(t[id].ch[1],v)); } int get_next (int id,int v) { if (!id) return inf; if (t[id].v<=v) return get_next(t[id].ch[1],v); else return min(t[id].v,get_next(t[id].ch[0],v)); } struct node { int l,r,root; }segTree[maxn*3]; void seg_build (int i,int l,int r) { segTree[i].l=l; segTree[i].r=r; for (int p=l;p<=r;p++) ins(segTree[i].root,a[p]); if (l==r) return; int mid=(l+r)>>1; seg_build(i<<1,l,mid); seg_build(i<<1|1,mid+1,r); } void modify (int i,int x,int y) { remove(segTree[i].root,a[x]); ins(segTree[i].root,y); if (segTree[i].l==segTree[i].r) return; int mid=(segTree[i].l+segTree[i].r)>>1; if (x>mid) modify(i<<1|1,x,y); else modify(i<<1,x,y); } int query_rank (int i,int l,int r,int k) { //查询某数的排名 if (segTree[i].l>r||segTree[i].r<l) return 0; if (segTree[i].l>=l&&segTree[i].r<=r) return rk(segTree[i].root,k); else return query_rank(i<<1,l,r,k)+query_rank(i<<1|1,l,r,k); } int query_kth (int u,int v,int k) { //查询区间第k大 int l=0,r=1e8; while (l<=r) { int mid=(l+r)>>1; if (query_rank(1,u,v,mid)<k) l=mid+1; else r=mid-1; } return r; } int query_pre (int i,int l,int r,int k) { //查询区间前驱 if (segTree[i].l>r||segTree[i].r<l) return -2147483647; if (segTree[i].l>=l&&segTree[i].r<=r) return get_pre(segTree[i].root,k); else return max(query_pre(i<<1,l,r,k),query_pre(i<<1|1,l,r,k)); } int query_nxt (int i,int l,int r,int k) { if (segTree[i].l>r||segTree[i].r<l) return 2147483647; if (segTree[i].l>=l&&segTree[i].r<=r) return get_next(segTree[i].root,k); else return min(query_nxt(i<<1,l,r,k),query_nxt(i<<1|1,l,r,k)); } int main () { int n,m; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",a+i); seg_build(1,1,n); for (int i=0;i<m;i++) { int op; scanf("%d",&op); if (op==1) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",query_rank(1,l,r,k)+1); } if (op==2) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",query_kth(l,r,k)); } if (op==3) { int x,y; scanf("%d%d",&x,&y); modify(1,x,y); a[x]=y; } if (op==4) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",query_pre(1,l,r,k)); } if (op==5) { int l,r,k; scanf("%d%d%d",&l,&r,&k); printf("%d\n",query_nxt(1,l,r,k)); } } return 0; }