\(\text{Problem}\)

动态区间第 \(k\) 小

Dynamic Rankings

\(\text{Analysis}\)

整体二分

原本一个询问可二分,但多个询问效率太低

考虑离线,把修改和询问扔到一起

二分答案,运用树状数组之类的东西处理完修改操作

依次检查询问,划分左右,初步确定每个询问的答案值域,修改操作相应地划分到有必要的一边(左右)

\(\text{Code}\)

#include<cstdio>
using namespace std; const int N = 1e5 + 5;
int n, m, cnt, a[N], ans[N], T[N]; struct node{
int ty, l, r, k, id;
}q[N * 3], q1[N * 3], q2[N * 3]; inline void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
} inline int lowbit(int x){return x & (-x);}
inline void add(int x, int v){for(; x <= n; x += lowbit(x)) T[x] += v;}
inline int query(int x)
{
int ret = 0;
for(; x; x -= lowbit(x)) ret += T[x];
return ret;
} void solve(int l, int r, int ql, int qr)
{
if (ql > qr) return;
if (l == r)
{
for(int i = ql; i <= qr; i++) ans[q[i].id] = l;
return;
}
int ct1 = 0, ct2 = 0, mid = (l + r) >> 1;
for(int i = ql; i <= qr; i++)
{
if (q[i].ty == 1)
{
if (q[i].l <= mid) add(q[i].r, q[i].k), q1[++ct1] = q[i];
else q2[++ct2] = q[i];
}
else{
int sum = query(q[i].r) - query(q[i].l - 1);
if (sum >= q[i].k) q1[++ct1] = q[i];
else q[i].k -= sum, q2[++ct2] = q[i];
}
}
for(int i = 1; i <= ct1; i++)
if (q1[i].ty == 1) add(q1[i].r, -q1[i].k);
for(int i = 1; i <= ct1; i++) q[ql + i - 1] = q1[i];
for(int i = 1; i <= ct2; i++) q[ql + ct1 + i - 1] = q2[i];
solve(l, mid, ql, ql + ct1 - 1);
solve(mid + 1, r, ql + ct1, qr);
} int main()
{
read(n), read(m);
for(int i = 1; i <= n; i++) read(a[i]), q[++cnt] = node{1, a[i], i, 1};
char op[3];
for(int i = 1, l, r, k; i <= m; i++)
{
scanf("%s", op), read(l), read(r);
if (op[0] == 'C') q[++cnt] = node{1, a[l], l, -1}, q[++cnt] = node{1, a[l] = r, l, 1};
else read(k), q[++cnt] = node{2, l, r, k, i};
}
solve(0, 1e9, 1, cnt);
for(int i = 1; i <= m; i++)
if (ans[i]) printf("%d\n", ans[i]);
}

当然可以树状数组套权值线段树

\(\text{Code}\)

#include <cstdio>
#include <algorithm>
#include <iostream>
#define re register
using namespace std; const int N = 1e5 + 5;
int n, m, len, a[N], b[N * 2], ct1, ct2, tmp1[50], tmp2[50];
struct que{int o, l, r, k;}q[N]; inline void read(int &x)
{
x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = (x<<3)+(x<<1)+(ch^48), ch = getchar();
} int size, rt[N], sum[N * 400], ls[N * 400], rs[N * 400];
void modify(int &p, int l, int r, int x, int v)
{
if (!p) p = ++size;
sum[p] += v;
if (l == r) return;
int mid = (l + r) >> 1;
if (x <= mid) modify(ls[p], l, mid, x, v);
else modify(rs[p], mid + 1, r, x, v);
}
int query(int l, int r, int k)
{
if (l == r) return l;
int s = 0, mid = (l + r) >> 1;
for(re int i = 1; i <= ct1; i++) s += sum[ls[tmp1[i]]];
for(re int i = 1; i <= ct2; i++) s -= sum[ls[tmp2[i]]];
if (k <= s)
{
for(re int i = 1; i <= ct1; i++) tmp1[i] = ls[tmp1[i]];
for(re int i = 1; i <= ct2; i++) tmp2[i] = ls[tmp2[i]];
return query(l, mid, k);
}
else{
for(re int i = 1; i <= ct1; i++) tmp1[i] = rs[tmp1[i]];
for(re int i = 1; i <= ct2; i++) tmp2[i] = rs[tmp2[i]];
return query(mid + 1, r, k - s);
}
} inline int lowbit(int x){return x & (-x);}
inline void Modify(int x, int val, int v)
{
val = lower_bound(b + 1, b + len + 1, val) - b;
for(; x <= n; x += lowbit(x)) modify(rt[x], 1, len, val, v);
}
inline int Query(int l, int r, int k)
{
ct1 = ct2 = 0;
for(; r; r -= lowbit(r)) tmp1[++ct1] = rt[r];
for(l = l - 1; l; l -= lowbit(l)) tmp2[++ct2] = rt[l];
return b[query(1, len, k)];
} int main()
{
read(n), read(m);
for(re int i = 1; i <= n; i++) read(a[i]), b[++len] = a[i];
int l, r, k; char op[3];
for(re int i = 1; i <= m; i++)
{
scanf("%s", op), read(l), read(r);
if (op[0] == 'Q') read(k), q[i] = que{1, l, r, k};
else q[i] = que{0, l, r}, b[++len] = r;
}
sort(b + 1, b + len + 1);
len = unique(b + 1, b + len + 1) - b - 1;
for(re int i = 1; i <= n; i++) Modify(i, a[i], 1);
for(re int i = 1; i <= m; i++)
if (q[i].o == 1) printf("%d\n", Query(q[i].l, q[i].r, q[i].k));
else Modify(q[i].l, a[q[i].l], -1), Modify(q[i].l, a[q[i].l] = q[i].r, 1);
}

最新文章

  1. centos7下操作防火墙
  2. python——线程与多线程进阶
  3. 硬件断点 DrxHook
  4. 8.PHP内核探索:再次探讨SAPI
  5. 推荐系统之LFM(二)
  6. 【原】yield的最基本用法
  7. DOC下编译和运行带有包的java类文件
  8. Android Studio的使用(五)--导入第三方Jar包
  9. Java中整形、浮点、字符之间的转换
  10. 【java设计模式】【创建模式Creational Pattern】建造模式Builder Pattern
  11. Checksum软件的简单设计
  12. DB Query Analyzer 5.05 is released, 65 articles concerned have been published
  13. Linux 6.8 TFS(Taobao File System)使用文档-安装篇
  14. grid布局
  15. Java数据类型Stack栈、Queue队列、数组队列和循环队列的比较
  16. 149. Max Points on a Line同一条线上的最多点数
  17. python-ldap修改AD域用户密码(CA+SSL)
  18. Develop with asyncio部分的翻译
  19. Apache Spark探秘:利用Intellij IDEA构建开发环境
  20. python全栈开发-面向对象-进阶2

热门文章

  1. fbterm的配置,纯文本终端显示中文
  2. Docker 工作原理分析
  3. python-简单模块的使用
  4. 目标检测模型的评价标准-AP与mAP
  5. Idea中Git的常用操作及可能存在的问题
  6. 2.2:常用的Python数据类型、字符串、dtype
  7. 【消息队列面试】15-17:高性能和高吞吐、pull和push、各种MQ的区别
  8. jjava基础语法
  9. 跟我学Python图像处理丨图像分类原理与案例
  10. 预编译SQL为什么能够防止SQL注入