[COGS257]动态排名系统 树状数组套主席树
2017-08-02 19:14
344 查看
257. 动态排名系统
时间限制:5 s 内存限制:512 MB[问题描述]
给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
1、查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
2、修改A[i]的值为j。
所谓排名第k,指一些数按照升序排列后,第k位的数。例如序列{6,1,9,6,6},排名第3的数是6,排名第5的数是9。
[输入格式]
第一行包含一个整数D(0<=D<=4),表示测试数据的数目。接下来有D组测试数据,每组测试数据中,首先是两个整数N(1<=N<=50000),M(1<=M<=10000),表示序列的长度为N,有M个操作。接下来的N个不大于1,000,000,000正整数,第i个表示序列A[i]的初始值。然后的M行,每行为一个操作
Q i j k 或者
C i j
分别表示查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数,和修改A[i]的值为j。
[输出格式]
对于每个查询,输出一行整数,为查询的结果。测试数据之间不应有空行。
[样例输入]
2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
[样例输出]
3
6
3
6
题解:
(如果你没有听过“树状数组套主席树”这个概念,你选择可以移步我的讲解http://www.cnblogs.com/LadyLex/p/7275164.html)
本题就是一个树状数组套主席树的板子题,如果用指针打的话操作时可以用vector存下需要更改的几棵树,进行修改
查询时候和普通的静态查询也是类似的,只不过是子树数据数量之和与k比较
这些东西还是通过代码可以更好的理解……代码见下:
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N=10100,MAXN=1000000000ll; int n,val ,tp; struct node { node *ch[2];int cnt; node(){cnt=0;ch[1]=ch[0]=NULL;} inline void update(){cnt=ch[0]->cnt+ch[1]->cnt;} }*null=new node(),*root[N*2]; vector<node*>v[5]; inline node* newnode() { node *o=new node(); o->ch[0]=o->ch[1]=null; return o; } inline int lowbit(int a){return a&-a;} inline void get_query(int id,int pos) { v[id].clear(); while(pos)v[id].push_back(root[pos]),pos-=lowbit(pos); } inline void get_set(int id,int pos) { v[id].clear(); while(pos<=n)v[id].push_back(root[pos]),pos+=lowbit(pos); } inline void set(vector<node*> o,int l,int r,int pos,int opt) { while(l<r) { int mi=(l+r)>>1; for(int i=0,len=o.size();i<len;i++)if(o[i]!=null)o[i]->cnt+=opt; if(pos<=mi) { r=mi; for(int i=0,len=o.size();i<len;o[i]=o[i]->ch[0],i++) if(o[i]->ch[0]==null)o[i]->ch[0]=newnode(); } else { l=mi+1; for(int i=0,len=o.size();i<len;o[i]=o[i]->ch[1],i++) if(o[i]->ch[1]==null)o[i]->ch[1]=newnode(); } } for(int i=0,len=o.size();i<len;i++) { if(o[i]==null)o[i]=newnode(); o[i]->cnt+=opt; } } inline int query(int a,int b,int l,int r,int k) { get_query(1,a-1);get_query(2,b); while(l<r) { int tmp=0,mi=(l+r)>>1; for(int i=0,len=v[1].size();i<len;i++)if(v[1][i]!=null)tmp-=v[1][i]->ch[0]->cnt; for(int i=0,len=v[2].size();i<len;i++)if(v[2][i]!=null)tmp+=v[2][i]->ch[0]->cnt; if(tmp>=k) { for(int i=0,len=v[1].size();i<len;i++)v[1][i]=v[1][i]->ch[0]; for(int i=0,len=v[2].size();i<len;i++)v[2][i]=v[2][i]->ch[0]; r=mi; } else { for(int i=0,len=v[1].size();i<len;i++)v[1][i]=v[1][i]->ch[1]; for(int i=0,len=v[2].size();i<len;i++)v[2][i]=v[2][i]->ch[1]; k-=tmp,l=mi+1; } } return r; } inline void change(int a,int b) {get_set(1,a);set(v[1],1,MAXN,val[a],-1);set(v[1],1,MAXN,b,1);val[a]=b;} int main() { int m,a,b,c;char s[3]; null->ch[0]=null->ch[1]=null; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)root[i]=newnode(); for(int i=1;i<=n;i++)scanf("%d",&val[i]),get_set(1,i),set(v[1],1,MAXN,val[i],1); while(m--) { scanf("%s",s); if(s[0]=='Q')scanf("%d%d%d",&a,&b,&c),printf("%d\n",query(a,b,1,MAXN,c)); else scanf("%d%d",&a,&b),change(a,b); } }
相关文章推荐
- bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统)
- 【COGS257】动态排名系统
- COGS-257-动态排名系统-树状数组+主席树
- 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树
- 【BIT套主席树】COGS257-动态排名系统
- 【COGS】257 动态排名系统 【动态第K小】树状数组+主席树
- Cogs_动态排名系统[整体二分]
- COGS 197 [HAOI2008] 排名系统
- BZOJ 1056([HAOI2008]排名系统-Treap旋转概率)
- Java 程序设计 利用线程实现动态显示系统时间
- 在网页中动态显示当前的系统日期和时间(最简代码)
- 基于spring+struts2+ibatis+OperaMasks实现的小系统(实现权限管理和动态开发)
- 【小松教你手游开发】【系统模块开发】动态可拖动列表DynmicList,ScrollView
- [BZOJ1901]Dynamic Rankings 动态排名
- 基于 Jython 的大型应用系统动态实现
- Java动态实现创建目录并以当前系统时间作为文件名
- UGUI基于EventTrigger的UI交互事件监听系统&动态加载
- Android系统 小米/三星/索尼 应用启动图标未读消息数(BadgeNumber)动态提醒
- 获取系统时间,动态显示
- Delphi 菜单的应用(系统菜单添加一项、主菜单增加历史记录、弹出菜单的动态合并、菜单中画图、显示状态)