#include<queue>
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
int n, m, a[50001], root, tot;
int op, x, y, z;
struct Tree_in {
int ls, rs, sz, yj, val;
}tree[4000001];
struct Tree_out {
int rt;
}t[200001];
int newpoint(int num) {
int re = ++tot;
tree[re] = (Tree_in){0, 0, 1, rand(), num};
return re;
}
void up(int now) {
tree[now].sz = tree[tree[now].ls].sz + tree[tree[now].rs].sz + 1;
}
pair <int, int> split_val(int now, int val) {
if (!now) return make_pair(0, 0);
pair <int, int> re;
if (val < tree[now].val) {
re = split_val(tree[now].ls, val);
tree[now].ls = re.second;
up(now);
re.second = now;
}
else {
re = split_val(tree[now].rs, val);
tree[now].rs = re.first;
up(now);
re.first = now;
}
return re;
}
int merge(int x, int y) {
if (!x) return y;
if (!y) return x;
if (tree[x].yj < tree[y].yj) {
tree[x].rs = merge(tree[x].rs, y);
up(x);
return x;
}
else {
tree[y].ls = merge(x, tree[y].ls);
up(y);
return y;
}
}
void insert_(int &now, int num) {
pair <int, int> x = split_val(now, num);
now = merge(merge(x.first, newpoint(num)), x.second);
}
int ask_bigger_(int &now, int num) {
pair <int, int> x = split_val(now, num);
int re = tree[x.first].sz;
now = merge(x.first, x.second);
return re;
}
void delete_(int &now, int num) {
pair <int, int> x = split_val(now, num);
pair <int, int> y = split_val(x.first, num - 1);
y.second = merge(tree[y.second].ls, tree[y.second].rs);
now = merge(merge(y.first, y.second), x.second);
}
int ask_pre_(int &now, int num) {
pair <int, int> x = split_val(now, num - 1);
int X = x.first, lst = -2147483647;
while (X) {
lst = X;
X = tree[X].rs;
}
now = merge(x.first, x.second);
if (lst == -2147483647) return lst;
return tree[lst].val;
}
int ask_nxt_(int &now, int num) {
pair <int, int> x = split_val(now, num);
int X = x.second, lst = 2147483647;
while (X) {
lst = X;
X = tree[X].ls;
}
now = merge(x.first, x.second);
if (lst == 2147483647) return lst;
return tree[lst].val;
}
void build(int now, int l, int r) {
if (l == r) {
t[now].rt = newpoint(a[l]);
return ;
}
else {
for (int i = l; i <= r; i++)
insert_(t[now].rt, a[i]);
}
int mid = (l + r) >> 1;
build(now << 1, l, mid);
build(now << 1 | 1, mid + 1, r);
}
int ask_bigger(int now, int l, int r, int L, int R, int num) {
if (L <= l && r <= R) {
return ask_bigger_(t[now].rt, num);
}
int re = 0, mid = (l + r) >> 1;
if (L <= mid) re += ask_bigger(now << 1, l, mid, L, R, num);
if (mid < R) re += ask_bigger(now << 1 | 1, mid + 1, r, L, R, num);
return re;
}
int ask_kth(int l, int r, int rnk) {
int L = 0, R = 1e8, ans = 0;
while (L <= R) {
int mid = (L + R) >> 1;
if (ask_bigger(1, 1, n, l, r, mid - 1) + 1 <= rnk) {
ans = mid;
L = mid + 1;
}
else R = mid - 1;
}
return ans;
}
void change(int now, int l, int r, int pl, int num) {
delete_(t[now].rt, a[pl]);
insert_(t[now].rt, num);
if (l == r) return ;
int mid = (l + r) >> 1;
if (pl <= mid) change(now << 1, l, mid, pl, num);
else change(now << 1 | 1, mid + 1, r, pl, num);
}
int ask_pre(int now, int l, int r, int L, int R, int num) {
if (L <= l && r <= R) {
return ask_pre_(t[now].rt, num);
}
int mid = (l + r) >> 1, re = -2147483647;
if (L <= mid) re = max(re, ask_pre(now << 1, l, mid, L, R, num));
if (mid < R) re = max(re, ask_pre(now << 1 | 1, mid + 1, r, L, R, num));
return re;
}
int ask_nxt(int now, int l, int r, int L, int R, int num) {
if (L <= l && r <= R) {
return ask_nxt_(t[now].rt, num);
}
int mid = (l + r) >> 1, re = 2147483647;
if (L <= mid) re = min(re, ask_nxt(now << 1, l, mid, L, R, num));
if (mid < R) re = min(re, ask_nxt(now << 1 | 1, mid + 1, r, L, R, num));
return re;
}
int main() {
srand(19491001);
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
build(1, 1, n);
while (m--) {
scanf("%d", &op);
if (op == 1) {
scanf("%d %d %d", &x, &y, &z);
printf("%d\n", ask_bigger(1, 1, n, x, y, z - 1) + 1);
continue;
}
if (op == 2) {
scanf("%d %d %d", &x, &y, &z);
printf("%d\n", ask_kth(x, y, z));
continue;
}
if (op == 3) {
scanf("%d %d", &x, &y);
change(1, 1, n, x, y);
a[x] = y;
continue;
}
if (op == 4) {
scanf("%d %d %d", &x, &y, &z);
printf("%d\n", ask_pre(1, 1, n, x, y, z));
continue;
}
if (op == 5) {
scanf("%d %d %d", &x, &y, &z);
printf("%d\n", ask_nxt(1, 1, n, x, y, z));
continue;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现