[bzoj1901][Zju2112]Dynamic Rankings_主席树
Dynamic Rankings bzoj-1901 Zju-2112
题目大意:给定一个n个数的序列,m个操作,支持:单点修改;查询区间k小值。
注释:$1\le n,m\le 10^4$。
想法:如果这个教树套树的话,我也没办法。
其实就是借用了树状数组的思想,我们在这里叫它...阉割树状数组把。
具体地,主席树每个节点维护的仍然是前缀权值线段树。
修改的时候将修改的点二进制lowbit分解。在分解的节点的权值线段树上直接修改。
查询时我们将所有区间(左端点-1)都二进制lowbit分解,然后每个点的sum都在delta上修改,判断进左子树还是右子树即可。
最后,附上丑陋的代码... ...
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 | #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 100500 int sum[N<<5],ls[N<<5],rs[N<<5],n,m,root[N<<5]; int sx[N],sy[N],v[N],maxn=1e9+10,cnt,cntx,cnty; char ch[10]; inline int lowbit( int i){ return i&(-i);} // int build(int l,int r) // { // int pos=++cnt,mid=(l+r)>>1; // if(l==r) return pos; // ls[pos]=build(l,mid); // rs[pos]=build(mid+1,r); // return pos; // } int update( int pre, int l, int r, int k, int val) { int pos=++cnt,mid=(l+r)>>1; sum[pos]=sum[pre]+val; ls[pos]=ls[pre]; rs[pos]=rs[pre]; if (l==r) return pos; if (k<=mid) ls[pos]=update(ls[pre],l,mid,k,val); else rs[pos]=update(rs[pre],mid+1,r,k,val); return pos; } int query( int l, int r, int k) { if (l==r) return l; int dlt=0,mid=(l+r)>>1; for ( int i=1;i<=cntx;i++) dlt-=sum[ls[sx[i]]]; for ( int i=1;i<=cnty;i++) dlt+=sum[ls[sy[i]]]; if (k<=dlt) { for ( int i=1;i<=cntx;i++) sx[i]=ls[sx[i]]; for ( int i=1;i<=cnty;i++) sy[i]=ls[sy[i]]; return query(l,mid,k); } else { for ( int i=1;i<=cntx;i++) sx[i]=rs[sx[i]]; for ( int i=1;i<=cnty;i++) sy[i]=rs[sy[i]]; return query(mid+1,r,k-dlt); } } int main() { int x,y,z; scanf ( "%d%d" ,&n,&m); for ( int i=1;i<=n;i++) { scanf ( "%d" ,&v[i]); for ( int j=i;j<=(n<<1);j+=lowbit(j)) root[j]=update(root[j],0,maxn,v[i],1); } for ( int i=1;i<=m;i++) { scanf ( "%s%d%d" ,ch,&x,&y); if (ch[0]== 'C' ) { for ( int j=x;j<=n;j+=lowbit(j)) root[j]=update(root[j],0,maxn,v[x],-1); v[x]=y; for ( int j=x;j<=n;j+=lowbit(j)) root[j]=update(root[j],0,maxn,v[x],1); } else { scanf ( "%d" ,&z); cntx=cnty=0; for ( int j=x-1;j;j-=lowbit(j)) sx[++cntx]=root[j]; for ( int j=y;j;j-=lowbit(j)) sy[++cnty]=root[j]; printf ( "%d\n" ,query(0,maxn,z)); } } } /* 5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3 */ |
小结:有趣...
| 欢迎来原网站坐坐! >原文链接<
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步