原题链接:Yuuki and a problem
查询与2020赛季icpc昆明M相同:[l,r]区间内无法最小无法合成的数,相比昆明加入了修改。
ICPC昆明M
对以root[i]为根的树进行修改会影响以root[i+1…n]为根的树。修改的时间代价太大。
采用树状数组维护主席树的每个版本。每次修改为
O
(
l
o
g
N
)
O(logN)
O(logN),因此修改的时间复杂度最坏为
O
(
N
l
o
g
2
N
)
O(Nlog^2N)
O(Nlog2N).
今天第一次做踩了一个坑: 每次修改时若还未对某个节点分配一个idx才分配,对分配好的使用原来的即可,否则开辟的节点数会非常大(超出内存限制),且很多都是没用的。
#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
using namespace std;
typedef long long LL;
const int N = 200010, INF = 200000;
struct Node {
int l, r;
LL s;
}tr[N * 100];
int n, m, a[N];
int root[N], idx, rt;
int ins(int v, int l, int r, int k, int x) {
int u = v;
if (u == 0) u = ++ idx; //未分配才分配
tr[u] = tr[v];
tr[u].s += x;
if (l == r) return u;
int mid = l + r >> 1;
if (k <= mid) tr[u].l = ins(tr[v].l, l, mid, k, x);
else tr[u].r = ins(tr[v].r, mid + 1, r, k , x);
return u;
}
LL query(int u, int l, int r, LL k) {
if (u == 0 || l == r) return tr[u].s;
int mid = l + r >> 1;
if (k <= mid) return query(tr[u].l, l, mid, k);
else return tr[tr[u].l].s + query(tr[u].r, mid + 1, r, k);
}
void ins(int x, int y, int z) {
for (int i = x; i <= n; i += lowbit(i)) root[i] = ins(root[i], 1, INF, y, z);
}
LL query(int l, int r, LL x) {
LL res = 0;
for (int i = r; i; i -= lowbit(i)) res += query(root[i], 1, INF, x);
for (int i = l - 1; i; i -= lowbit(i)) res -= query(root[i], 1, INF, x);
return res;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
ins(i, a[i], a[i]);
}
while (m --) {
int op, l, r;
cin >> op >> l >> r;
if (op == 1) {
ins(l, a[l], -a[l]);
a[l] = r;
ins(l, a[l], a[l]);
}
else {
LL ans = 0;
LL t;
while ((t = query(l, r, ans + 1)) > ans) ans = t;
cout << ans + 1 << endl;
}
}
return 0;
}