博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HYSBZ 1901 Dynamic Rankings
阅读量:4975 次
发布时间:2019-06-12

本文共 3951 字,大约阅读时间需要 13 分钟。

题意:

给定一个长度为n的序列,有m次操作,分别为以下两种情况:
1.Q left right k,查询[left,right]中的第k小数
2.C at data,将第x位的数修改为data
题解:
①带修改的主席树=主席树+树状数组
②与POJ 2104 K-th Number类似,只不过加上了修改操作
③考虑每一次修改操作,实际上它只会对[at,n]的区间产生影响
④我们可以开一个树状数组来记录这些修改,树状数组的每一个点都是一颗线段树
⑤查询的时候只要将原来的查询加上树状数组上的查询即可

 

#include 
#include
#include
using namespace std;const int maxn=50000+10;struct Tree{ int lch,rch; int data;}a[maxn<<5];struct ASK{ int op; int left,right,k; int at,data;}q[maxn];int n,m,A[maxn];int Map[maxn],cnt;int root[maxn],num;int C[maxn],use[maxn];void Init();void Build(int&,int,int);void Update(int&,int,int,int,int,int);int Query(int,int,int,int,int,int,int);int Lowbit(int);void Add(int,int,int);int GetSum(int);signed main(){ // freopen("in.cpp","r",stdin); int t;scanf("%d",&t); while(t--)Init(); return 0;}void Init(){ num=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&A[i]),Map[++cnt]=A[i]; char op; for(int i=1;i<=m;i++){ scanf(" %c",&op); if(op=='Q')q[i].op=1,scanf("%d%d%d",&q[i].left,&q[i].right,&q[i].k); else q[i].op=0,scanf("%d%d",&q[i].at,&q[i].data),Map[++cnt]=q[i].data; } sort(Map+1,Map+1+cnt);cnt=unique(Map+1,Map+1+cnt)-Map-1; Build(root[0],1,cnt); for(int i=1;i<=n;i++){ int x=lower_bound(Map+1,Map+1+cnt,A[i])-Map; Update(root[i],root[i-1],1,cnt,x,1); } for(int i=1;i<=n;i++)C[i]=root[0]; for(int i=1,x;i<=m;i++){ if(q[i].op){ for(int j=q[i].left-1;j;j-=Lowbit(j)) use[j]=C[j]; for(int j=q[i].right;j;j-=Lowbit(j)) use[j]=C[j]; x=Query(root[q[i].left-1],root[q[i].right],q[i].left-1,q[i].right,1,cnt,q[i].k); printf("%d\n",Map[x]); } else{ x=lower_bound(Map+1,Map+1+cnt,A[q[i].at])-Map; Add(q[i].at,x,-1); x=lower_bound(Map+1,Map+1+cnt,q[i].data)-Map; Add(q[i].at,x,1); A[q[i].at]=q[i].data; } }}void Build(int &u,int left,int right){ u=++num; a[u].data=0; if(left==right)return; int mid=(left+right)>>1; Build(a[u].lch,left,mid); Build(a[u].rch,mid+1,right);}void Update(int &u,int y,int left,int right,int pos,int key){ u=++num; a[u].lch=a[y].lch;a[u].rch=a[y].rch; a[u].data=a[y].data+key; if(left==right)return; int mid=(left+right)>>1; if(pos<=mid)Update(a[u].lch,a[y].lch,left,mid,pos,key); else Update(a[u].rch,a[y].rch,mid+1,right,pos,key);}int Query(int u,int v,int L,int R,int left,int right,int k){ if(left==right)return left; int mid=(left+right)>>1; int data=GetSum(R)-GetSum(L)+a[a[v].lch].data-a[a[u].lch].data; if(data>=k){ for(int i=L;i;i-=Lowbit(i)) use[i]=a[use[i]].lch; for(int i=R;i;i-=Lowbit(i)) use[i]=a[use[i]].lch; return Query(a[u].lch,a[v].lch,L,R,left,mid,k); } else{ for(int i=L;i;i-=Lowbit(i)) use[i]=a[use[i]].rch; for(int i=R;i;i-=Lowbit(i)) use[i]=a[use[i]].rch; return Query(a[u].rch,a[v].rch,L,R,mid+1,right,k-data); }}int Lowbit(int x){ return x&(-x);}void Add(int x,int pos,int key){ for(int i=x;i<=n;i+=Lowbit(i)) Update(C[i],C[i],1,cnt,pos,key);}int GetSum(int x){ int ans=0; for(int i=x;i;i-=Lowbit(i)) ans+=a[a[use[i]].lch].data; return ans;}

 

转载于:https://www.cnblogs.com/holy-unicorn/p/9510321.html

你可能感兴趣的文章
SELECT LOCK IN SHARE MODE and FOR UPDATE
查看>>
Perl/Nagios – Can’t locate utils.pm in @INC
查看>>
目录导航「深入浅出ASP.NET Core系列」
查看>>
Javascript 有用参考函数
查看>>
点群的判别(三)
查看>>
GNSS 使用DFT算法 能量损耗仿真
查看>>
【转】Simulink模型架构指导
查看>>
MYSQL数据库的导出的几种方法
查看>>
硬件之美
查看>>
[转载]java开发中的23种设计模式
查看>>
表格的拖拽功能
查看>>
函数的形参和实参
查看>>
【TP SRM 703 div2 500】 GCDGraph
查看>>
webdriver api
查看>>
apache 实现图标缓存客户端
查看>>
揭秘:黑客必备的Kali Linux是什么,有哪些弊端?
查看>>
linux系统的远程控制方法——学神IT教育
查看>>
springboot+mybatis报错Invalid bound statement (not found)
查看>>
Linux环境下SolrCloud集群环境搭建关键步骤
查看>>
MongoDB的简单使用
查看>>