请你写出一种数据结构,来维护一个长度为 n 的序列,其中需要提供以下操作:
1 pos x
,将 pos 位置的数修改为 x。2 l r x
,查询整数 x 在区间 [ll,r] 内的前驱(前驱定义为小于 x,且最大的数)。
数列中的位置从左到右依次标号为 1∼n。
区间 [l,r] 表示从位置 l 到位置 r 之间(包括两端点)的所有数字。
区间内排名为 k 的值指区间内从小到大排在第 k 位的数值。(位次从 1 开始)
输入格式
第一行包含两个整数 n,m,表示数列长度以及操作次数。
第二行包含 n 个整数,表示有序数列。
接下来 m 行,每行包含一个操作指令,格式如题目所述。
输出格式
对于所有操作 2,每个操作输出一个查询结果,每个结果占一行。
数据范围
1≤n,m≤5×104
1≤l≤r≤n
1≤pos≤n
0≤x≤108
有序数列中的数字始终满足在 [0,108] 范围内,
数据保证所有操作一定合法,所有查询一定有解。
输入样例:
5 3
3 4 2 1 5
2 2 4 4
1 3 5
2 2 4 4
输出样例:
2
1
解析:
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <utility>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <sstream>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <stdio.h>
#include <tuple>
using namespace std;
/*
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
*/
typedef long long LL;
//#define int long long
#define ld long double
//#define INT __int128
const LL INF = 0x3f3f3f3f3f3f3f3f;
typedef unsigned long long ULL;
typedef pair<long long, long long> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int inf = 0x3f3f3f3f;
const LL mod = 998244353;
const ld eps = 1e-12;
const int N = 5e4 + 10, M = 5e5 + 10;
int n, m;
int A[N];
struct TREE {
multiset<int>s;
}tr[N<<2];
#define ls u<<1
#define rs u<<1|1
void build(int l, int r, int u) {
tr[u].s.insert(-inf), tr[u].s.insert(inf);
for (int i = l; i <= r; i++) {
tr[u].s.insert(A[i]);
}
if (l == r)return;
int mid = l + r >> 1;
build(l, mid, ls), build(mid + 1, r, rs);
}
void modify(int l, int r, int u, int pos, int x) {
//cout << "____________" << l << " " << r << endl;
tr[u].s.erase(tr[u].s.find(A[pos]));
tr[u].s.insert(x);
//A[pos] = x;
if (l == r)return;
int mid = l + r >> 1;
if (pos <= mid)modify(l, mid, ls, pos, x);
if (pos > mid)modify(mid + 1, r, rs, pos, x);
}
int query(int l, int r, int u, int L, int R, int x) {
//cout << "___________" << l << " " << r << endl;
if (L <= l && r <= R) {
auto ret = tr[u].s.lower_bound(x);
ret--;
//cout << "______________" << l << " " << r << " " << *ret << endl;
return *ret;
}
int ret = -inf;
int mid = l + r >> 1;
if (L <= mid)ret = max(ret, query(l, mid, ls, L, R, x));
if (R > mid)ret = max(ret, query(mid+1, r, rs, L, R, x));
//cout << "________________" << l << " " << r << " " << ret << endl;
return ret;
}
signed main() {
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> A[i];
}
//A[0] = -inf, A[n + 1] = inf;
build(1, n, 1);
//n++;
int op;
while (m--) {
cin >> op;
if (op == 1) {
int pos, x;
cin >> pos >> x;
modify(1, n, 1, pos, x);
A[pos] = x;
}
else {
int l, r, x;
cin >> l >> r >> x;
cout << query(1, n, 1, l, r, x) << endl;
}
}
return 0;
}
/*
20 30
49 1 39 13 13 11 0 15 27 28 20 41 19 17 6 7 33 0 13 0
1 9 1
2 1 6 31
2 6 13 5
1 16 26
2 13 16 30
2 2 8 31
1 7 16
2 13 18 12
2 13 14 43
1 17 45
2 8 15 2
1 8 1
2 13 13 24
1 5 5
1 10 10
1 13 49
1 17 15
2 6 14 33
2 4 16 44
1 18 33
2 6 8 40
2 7 15 2
2 2 2 6
1 10 2
2 1 13 14
2 5 8 38
2 8 15 46
1 15 45
1 14 49
2 14 18 42
*/