Description:
1<=n,m<=1e5
时限:-O2,1s
空限:128MB
题解:
把询问区间的左端点视为x,右端点视为y。
转换模型后不难发现就是对二维平面上一些东西做一个东西。
设s表示一段时间内这个区间和的增量,v表示和的增量的历史版本最小值(v>=0)。
这个玩意显然是可以合并的,即有两个相邻的时间段的s和v,就可以合并出新的。
那么用二维线段树去维护这个吗?
空间爆了,且常数巨大。
所以可以用KD-tree维护
Code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define pp printf
#define ll long long
using namespace std;
const int N = 1e5 + 5;
int n, m, a[N], aa[N];
ll sa[N];
struct nod {
int op, x, y;
} b[N];
struct P {
int d[2], i;
} c[N]; int c0;
int D;
int cmp(P a, P b) {
return a.d[D] < b.d[D];
}
struct hh {
int l, r;
int d[2], mx[2], mi[2];
ll s, v, ls, lv;
} t[N];
int rt;
int To[N];
void mer(hh &a, hh b) {
fo(j, 0, 1) a.mi[j] = min(a.mi[j], b.mi[j]), a.mx[j] = max(a.mx[j], b.mx[j]);
}
void bt(int &i, int x, int y) {
int m = x + y >> 1; i = m;
nth_element(c + x, c + m, c + y + 1, cmp);
fo(j, 0, 1) t[i].mx[j] = t[i].mi[j] = t[i].d[j] = c[m].d[j];
To[c[m].i] = m;
D ^= 1;
if(x < m) bt(t[i].l, x, m - 1), mer(t[i], t[t[i].l]);
if(m < y) bt(t[i].r, m + 1, y), mer(t[i], t[t[i].r]);
D ^= 1;
}
int pl, pr, px, py;
ll ps, pv;
void add(ll &s, ll &v, ll ss, ll vv) {
v = min(v, s + vv);
s += ss;
}
void down(int i) {
if(t[i].ls || t[i].lv) {
add(t[t[i].l].s, t[t[i].l].v, t[i].ls, t[i].lv);
add(t[t[i].l].ls, t[t[i].l].lv, t[i].ls, t[i].lv);
add(t[t[i].r].s, t[t[i].r].v, t[i].ls, t[i].lv);
add(t[t[i].r].ls, t[t[i].r].lv, t[i].ls, t[i].lv);
t[i].ls = t[i].lv = 0;
}
}
void add(int i, int x, int y) {
if(t[i].mx[0] < pl || t[i].mi[0] > pr) return;
if(t[i].mx[1] < px || t[i].mi[1] > py) return;
if(t[i].mi[0] >= pl && t[i].mx[0] <= pr)
if(t[i].mi[1] >= px && t[i].mx[1] <= py) {
add(t[i].s, t[i].v, ps, pv);
add(t[i].ls, t[i].lv, ps, pv);
return;
}
if(t[i].d[0] >= pl && t[i].d[0] <= pr)
if(t[i].d[1] >= px && t[i].d[1] <= py)
add(t[i].s, t[i].v, ps, pv);
int m = x + y >> 1; down(i);
if(x < m) add(t[i].l, x, m - 1);
if(m < y) add(t[i].r, m + 1, y);
}
void ft(int i, int x, int y) {
if(y < pl || x > pr) return;
int m = x + y >> 1;
if(pl == m) {
pv = t[i].v; return;
}
down(i);
if(pl < m) ft(t[i].l, x, m - 1); else
ft(t[i].r, m + 1, y);
}
int main() {
freopen("ds.in", "r", stdin);
freopen("ds.out", "w", stdout);
scanf("%d %d", &n, &m);
fo(i, 1, n) scanf("%d", &a[i]), sa[i] = sa[i - 1] + a[i], aa[i] = a[i];
fo(i, 1, m) {
scanf("%d %d %d", &b[i].op, &b[i].x, &b[i].y);
if(b[i].op == 2) {
c0 ++;
c[c0].i = i;
c[c0].d[0] = b[i].x;
c[c0].d[1] = b[i].y;
}
}
bt(rt, 1, c0);
fo(i, 1, m) {
if(b[i].op == 1) {
pl = 1, pr = b[i].x;
px = b[i].x; py = n;
ps = b[i].y - a[b[i].x]; pv = min(0ll, ps);
a[b[i].x] = b[i].y;
add(rt, 1, c0);
} else {
pl = pr = To[i];
pv = 0;
ft(rt, 1, c0);
pp("%lld\n", pv + sa[b[i].y] - sa[b[i].x - 1]);
}
}
}