[BZOJ1901][ZJU2112]Dynamic Rankings
2016-02-01 10:30
465 查看
Zju2112 Dynamic Rankings
Description给定一个含有n个数的序列a[1],a[2],a[3]……a
,程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a
,这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
HINT
20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。
Solution :
简单来说就是带修改的区间第k大.
不带修改的时候我们有一个经典做法,就是利用可持久化线段树,对于每一个位置都建立一棵保存[1,i]的线段树,利用区间减法得到区间信息.
其实我们可以知道,上面这种做法其实就是做了一个前缀和,那么这里我们就是要维护前缀和.
对于一个数列来说维护前缀和很简单,通过树状数组实现即可,其实对于线段树,可以看成是很多数列构成的,我们同样可以利用树状数组维护.
Code
#include <bits/stdc++.h> using namespace std; #define rep(i, l, r) for (int i = (l); i <= (r); i++) #define per(i, r, l) for (int i = (r); i >= (l); i--) #define MS(_) memset(_, 0, sizeof(_)) #define MP make_pair #define PB push_back typedef long long ll; typedef pair<int, int> PII; template<typename T> inline void read(T &x){ x = 0; T f = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();} while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();} x *= f; } const int N = 10000 + 10; int n, m, top = 0, sz = 0, La, Lb, tot; int num[N<<1], v , A , B , K , flag ; int root , lc[N*100], rc[N*100], sum[N*100], L , R ; inline int lowbit(int x) { return x&-x; } inline void modify(int l, int r, int &x, int pos, int delta){ if (!x) x = ++sz; sum[x] += delta; if (l == r) return; int mid = l+r >> 1; if (pos <= mid) modify(l, mid, lc[x], pos, delta); else modify(mid+1, r, rc[x], pos, delta); } inline int query(int l, int r, int k){ if (l == r) return l; int suml = 0, sumr = 0; rep(i, 1, La) suml += sum[lc[L[i]]]; rep(i, 1, Lb) sumr += sum[lc[R[i]]]; int mid = (l+r)>>1; if (k <= sumr - suml){ rep(i, 1, La) L[i] = lc[L[i]]; rep(i, 1, Lb) R[i] = lc[R[i]]; return query(l, mid, k); }else{ rep(i, 1, La) L[i] = rc[L[i]]; rep(i, 1, Lb) R[i] = rc[R[i]]; return query(mid+1, r, k-(sumr-suml)); } } int main(){ read(n); read(m); rep(i, 1, n) scanf("%d", &v[i]), num[++top] = v[i]; rep(i, 1, m){ char ch[3]; scanf("%s%d%d", ch, &A[i], &B[i]); if (ch[0] == 'Q') { scanf("%d", &K[i]); flag[i] = 1; } else num[++top] = B[i]; } sort(num+1, num+1+top); tot = unique(num+1, num+1+top)-num-1; rep(i, 1, n){ int pos = upper_bound(num+1, num+1+tot, v[i])-num-1; for (int j = pos; j <= n; j += lowbit(j)) modify(1, tot, root[j], pos, 1); } rep(i, 1, m) if (flag[i]){ La = Lb = 0; A[i]--; for (int j = A[i]; j; j -= lowbit(j)) L[++La] = root[j]; for (int j = B[i]; j; j -= lowbit(j)) R[++Lb] = root[j]; printf("%d\n", num[query(1, tot, K[i])]); }else{ int pos = upper_bound(num+1, num+1+tot, v[A[i]])-num-1; for (int j = A[i]; j <= n; j += lowbit(j)) modify(1, tot, root[j], pos, -1); v[A[i]] = B[i]; pos = upper_bound(num+1, num+1+tot, v[A[i]])-num-1; for (int j = A[i]; j <= n; j += lowbit(j)) modify(1, tot, root[j], pos, 1); } return 0; }
相关文章推荐
- centos7下使用yum安装mysql
- 微信企业号开发(8)--示例代码
- windows上安装oracle 12c到69%时卡住不动解决方案
- 一步步搭建web服务器(2)
- HDU4869:Turn the pokers(费马小定理+高速幂)
- (NO.00005)iOS实现炸弹人游戏(九):游戏主角(二)
- Hadoop—FS Shell
- (NO.00005)iOS实现炸弹人游戏(九):游戏主角(二)
- (NO.00005)iOS实现炸弹人游戏(九):游戏主角(二)
- 浙江大华笔试题
- jQuery全选框单选框的实现效果
- 使用Native API查询Windows硬盘分区系统设备名称
- Linux命令行测试网速
- app服务器端开发之用户登录(struts2)处理
- C#调用命令行@服务
- hibernate 实体字段不映射到数据库
- android文件和图片的处理工具类(一)
- Linux创建以当前日期命名的文件夹
- .NET网站运行,无效的DateTime错误
- UITextFeild修改placeHolder的字号,颜色