hdu 5412 CRB and Queries 2015多校联合训练赛#10 分治 求区间第k大数
2015-08-22 11:39
721 查看
CRB and Queries
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 636 Accepted Submission(s): 162
Problem Description
There are N boys
in CodeLand.
Boy i has
his coding skill Ai.
CRB wants to know who has the suitable coding skill.
So you should treat the following two types of queries.
Query 1: 1 l v
The coding skill of Boy l has
changed to v.
Query 2: 2 l r k
This is a report query which asks the k-th
smallest value of coding skill between Boy l and
Boy r(both
inclusive).
Input
There are multiple test cases.
The first line contains a single integer N.
Next line contains N space
separated integers A1, A2,
…, AN,
where Ai denotes
initial coding skill of Boy i.
Next line contains a single integer Q representing
the number of queries.
Next Q lines
contain queries which can be any of the two types.
1 ≤ N, Q ≤ 105
1 ≤ Ai, v ≤ 109
1 ≤ l ≤ r ≤ N
1 ≤ k ≤ r – l +
1
Output
For each query of type 2, output a single integer corresponding to the answer in a single line.
Sample Input
5 1 2 3 4 5 3 2 2 4 2 1 3 6 2 2 4 2
Sample Output
3 4
Author
KUT(DPRK)
Source
2015 Multi-University Training Contest 10
求区间第k大数,http://www.cnblogs.com/zig-zag/archive/2013/04/18/3027707.html 参考这篇博客,然后看2013年集训队XHR论文。吧
解法:操作分三种,
1. 加入一个数,
2. 删除一个数,
3. 询问答案在左区间还是又区间
方法:
二分询问的答案是什么。
对于初始数字,变为插入操作
按操作的时间顺序排列各个操作,对于修改操作拆为删除和加入操作
:1 删除之前插入的数字,2. 加入新的数字
接下来分治二分答案:
对于mid,如果插入或者删除的数字<=mid那么应该放到左区间,并且用树状数组(其他数据结构也行)
维护前X个位置有多少个数字在左边。
对于询问:如果l,r区间在左边的数字>=k那么答案在左边,否则答案在右边,并且更新K,k=k-这个区间去左边的数字个数
当low =high的时候,说明low就是答案了,只要更新询问还在low,low之间的答案即可。
复杂度分析:分治的深度是log(S)s是数据的范围。
每个询问每次被分到左边或者右边,会有log(s)次操作。每个插入或者删除也是。
但是要用树状数组维护多少个数字在左边,要log(n)次更新或者查询。
复杂度是n*log(s)*log(n)
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<vector> using namespace std; #define maxn 300007 int tree[maxn]; void add(int p,int n){ for(;p<maxn;p+=p&(-p)) tree[p]+=n; } int query(int p){ int ans = 0; for(;p>0;p-=p&(-p)) ans += tree[p]; return ans; } struct Node{ int l,r,k,ty,ans; }; Node p[maxn]; int id1[maxn],id2[maxn]; void CDQ(int L,int R,int low,int high){ if(R < L) return ; if(low == high ){ for(;L<=R;L++){ p[id1[L]].ans = low; } return ; } int mid = (low+high)/2,l=L,r=R,k,u; for(int i = L;i <= R; i++){ u = id1[i]; if(p[u].ty == 2){ k = query(p[u].r) - query(p[u].l-1); if(k >= p[u].k) id2[l++] = u; else { p[u].k -= k; id2[r--] = u; } } else if(p[u].k <= mid){ add(p[u].l,p[u].ty); id2[l++] = u; } else id2[r--] = u; } for(int i = L; i <= R; i++){ u = id1[i]; if(p[u].ty != 2 && p[u].k <= mid) add(p[u].l,-p[u].ty); } for(k=L;k<l;k++) id1[k] = id2[k]; for(r=R;k<=R;k++) id1[k] = id2[r--]; CDQ(L,l-1,low,mid); CDQ(l,R,mid+1,high); } int num[maxn]; int main(){ int n,q,t,cnt; memset(tree,0,sizeof(tree)); while(scanf("%d",&n)!=EOF){ for(cnt=0;cnt<n;cnt++){ scanf("%d",&p[cnt].k); p[cnt].ty = 1; p[cnt].l = cnt+1; num[cnt+1] = p[cnt].k; } scanf("%d",&q); int ty,l,v; for(int i = 0;i < q; i++,cnt++){ scanf("%d",&p[cnt].ty); if(p[cnt].ty == 1){ scanf("%d%d",&l,&v); p[cnt].ty = -1; p[cnt].k = num[l]; p[cnt].l = l; cnt++; num[l] = v; p[cnt].ty = 1; p[cnt].k = v; p[cnt].l = l; } else { scanf("%d%d%d",&p[cnt].l,&p[cnt].r,&p[cnt].k); } } for(int i = 0;i < cnt; i++) id1[i] = i; CDQ(0,cnt-1,0,1000000000); for(int i = 0;i < cnt; i++){ if(p[i].ty == 2) printf("%d\n",p[i].ans); } } return 0; }
相关文章推荐
- UISegmentControl
- UILabel 根据内容的多少来计算label的frame
- Guest与virtio netdev交互模式
- POJ 2478 Farey Sequence
- Android source build/envsetup.sh 及lunch 过程
- UI-UILabel
- POJ 2487:Farey Sequence
- android模拟器 一个错误:X Error of failed request: BadRequest (invalid request code or no such operation)
- UIDatePicker的使用
- (java gui) 和 (网页 js) 通过url传值(如json)时,注意问题
- UITableView的简单使用
- 【转】自定义UITableViewCell(registerNib: 与 registerClass: 的区别)
- POJ---2524-Ubiquitous Religions(并查集)
- NGUI之图文混排
- UIPickerView的使用
- iOS UIControl 几个事件的说明
- 黑马程序员--OC之UIKit类的继承结构图
- xcode -UI 学习笔记
- 重用从xib加载的UITableViewCell
- HDU-5146_Sequence