Dynamic Rankings

带修改的区间第K大其实就是先和静态区间第K大的操作一样。先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树状数组的方式去修改,并且修改那些地方。查询的时候就是查询原主席树+树状数组的值。

代码:

 #include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
//#define lson l,m,rt<<1
//#define rson m+1,r,rt<<1|1
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const LL mod = (int)1e9+;
const int N = ;
const int M = ;
int root[N], S[N], lson[M], rson[M], ll[N], rr[N], cnt[M];
int tot, t;
int lsz, rsz;
int a[N], b[N];
struct Node{
int l, r, op, k;
}A[N];
int Build(int l, int r){
int now = ++tot;
cnt[now] = ;
if(l < r){
int m = l+r >> ;
lson[now] = Build(l,m);
rson[now] = Build(m+,r);
}
return now;
}
int Update(int l, int r, int pre, int pos, int v){
int now = ++tot;
cnt[now] = cnt[pre] + v;
if(l < r){
int m = l+r >> ;
if(pos <= m){
rson[now] = rson[pre];
lson[now] = Update(l, m, lson[pre], pos, v);
}
else {
lson[now] = lson[pre];
rson[now] = Update(m+, r, rson[pre], pos, v);
}
cnt[now] = cnt[lson[now]] + cnt[rson[now]];
}
return now;
}
int Query(int l, int r, int L, int R, int k){
if(l == r) return l;
int num1 = cnt[lson[L]];
int num2 = cnt[lson[R]];
for(int i = ; i <= lsz; i++) num1 += cnt[lson[ll[i]]];
for(int i = ; i <= rsz; i++) num2 += cnt[lson[rr[i]]];
num2 -= num1;
int m = l+r >> ;
if(num2 >= k){
for(int i = ; i <= lsz; i++) ll[i] = lson[ll[i]];
for(int i = ; i <= rsz; i++) rr[i] = lson[rr[i]];
return Query(l, m, lson[L], lson[R], k);
}
else {
for(int i = ; i <= lsz; i++) ll[i] = rson[ll[i]];
for(int i = ; i <= rsz; i++) rr[i] = rson[rr[i]];
return Query(m+, r, rson[L], rson[R], k-num2);
}
}
int id(int x){
return lower_bound(b+, b++t, x) - b;
}
int lowbit(int x){
return x&(-x);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
tot = t = ;
int n, m;
char s[];
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) scanf("%d", &a[i]), b[++t] = a[i];
for(int i = ; i <= m; i++){
scanf("%s", s);
if(s[] == 'Q'){
A[i].op = ;
scanf("%d%d%d", &A[i].l, &A[i].r, &A[i].k);
}
else {
A[i].op = ;
scanf("%d%d", &A[i].l, &A[i].r);
b[++t] = A[i].r;
}
}
sort(b+, b++t);
int tmp = ;
for(int i = ; i <= t; i++)
if(b[i] != b[i-]) b[++tmp] = b[i];
t = tmp;
root[] = Build(, t);
for(int i = ; i <= n; i++){
root[i] = Update(, t, root[i-], id(a[i]), );
}
for(int i = ; i <= n; i++) S[i] = root[];
for(int i = ; i <= m; i++){
if(A[i].op == ){
lsz = rsz = ;
for(int j = A[i].l-; j; j-=lowbit(j)) ll[++lsz] = S[j];
for(int j = A[i].r; j; j-=lowbit(j)) rr[++rsz] = S[j];
printf("%d\n", b[Query(,t,root[A[i].l-], root[A[i].r], A[i].k)]);
}
else {
for(int j = A[i].l; j <= t; j += lowbit(j)) S[j] = Update(, t, S[j], id(a[A[i].l]), -);
for(int j = A[i].l; j <= t; j += lowbit(j)) S[j] = Update(, t, S[j], id(A[i].r), );
a[A[i].l] = A[i].r;
}
}
}
return ;
}

ZOJ 2112

最新文章

  1. django-cms 代码研究(五)深入(代码结构)
  2. linux:网络yum源和制作本地光盘yum源
  3. 解析XML的四种方式
  4. Spring与Hibernate整合,实现Hibernate事务管理
  5. mybatis的动态sql
  6. php字符串截取问题
  7. Android ADB启动失败 ADB server out of date
  8. 小学生之深入C#
  9. 3.2 GUN as汇编(本文内容大部分引用原文,非原创)
  10. Flask导入静态文件问题
  11. Gradle入门到实战(一) — 全面了解Gradle
  12. mongo中的模糊查询
  13. .NET Threadpool的一点认识
  14. 【nginx&amp;php】后台权限认证方式
  15. VSTO:使用C#开发Excel、Word【15】
  16. 洛谷P2447 [SDOI2010]外星千足虫(异或方程组)
  17. [ASE][Daily Scrum]11.07-11.09
  18. Python与操作系统有关的模块
  19. arpspoof与其他几款工具的使用
  20. ajax 实现跨域

热门文章

  1. Mybatis连接查询返回类型问题
  2. abp(net core)+easyui+efcore实现仓储管理系统目录
  3. 在Vue 中使用Typescript
  4. 爬虫之爬取电影天堂(request)
  5. 洛谷 P1120 小木棍
  6. Java源码之阻塞队列
  7. java并发系列 - 第28天:实战篇,微服务日志的伤痛,一并帮你解决掉
  8. linux下搭建LJMT(图文版)
  9. gRPC快速入门记录
  10. 【原创】display:flex布局大全