传送门:CF
前言:嗯,看了题解就是一个普通的线段树,所以就是硬搞,嗯,搞,嗯,搞,嗯,搞。
于是一晚上的美好时间就被这道题搞没了......
具有纪念意义的AC代码如下:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct AC {
ll ln, rn, ls, rs, v;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
vector<int>v(n + 1);
for (int i = 1; i <= n; i++) {
cin >> v[i];
}
vector<AC>tre(n << 3);
function<void(int, int, int)>build = [&](int l, int r, int a) {
if (l == r) {
tre[a] = { v[l],v[r],1,1,1 };
return;
}
int mid = (l + r) >> 1;
build(l, mid, (a << 1));
build(mid + 1, r, (a << 1) | 1);
tre[a].ln = tre[(a << 1)].ln;
tre[a].rn = tre[(a << 1) | 1].rn;
if (tre[(a << 1)].rn <= tre[(a << 1) | 1].ln) {
tre[a].v = tre[a << 1].v + tre[(a << 1) | 1].v + (tre[a << 1].rs*tre[(a << 1) | 1].ls);
if (tre[(a << 1) | 1].rs >= (r - mid)) {
tre[a].rs = tre[(a << 1) | 1].rs + tre[a << 1].rs;
}
else {
tre[a].rs = tre[(a << 1) | 1].rs;
}
if (tre[a << 1].ls >= (mid - l + 1)) {
tre[a].ls = tre[a << 1].ls + tre[(a << 1) | 1].ls;
}
else {
tre[a].ls = tre[(a << 1)].ls;
}
}
else {
tre[a].v = tre[a << 1].v + tre[(a << 1) | 1].v;
tre[a].ls = tre[a << 1].ls;
tre[a].rs = tre[(a << 1) | 1].rs;
}
};
build(1, n, 1);
function<void(int, int, int, int, int)>update = [&](int pos, int t, int l, int r, int a) {
int mid = (l + r) >> 1;
if (l == r) {
tre[a] = { t,t,1,1,1 };
v[pos] = t;
return;
}
if (pos <= mid) {
update(pos, t, l, mid, (a << 1));
}
else {
update(pos, t, mid + 1,r,(a << 1) | 1);
}
tre[a].ln = tre[(a << 1)].ln;
tre[a].rn = tre[(a << 1) | 1].rn;
if (tre[(a << 1)].rn <= tre[(a << 1) | 1].ln) {
tre[a].v = tre[a << 1].v + tre[(a << 1) | 1].v + (tre[a << 1].rs*tre[(a << 1) | 1].ls);
if (tre[(a << 1) | 1].rs >= (r - mid)) {
tre[a].rs = tre[(a << 1) | 1].rs + tre[a << 1].rs;
}
else {
tre[a].rs = tre[(a << 1) | 1].rs;
}
if (tre[a << 1].ls >= (mid - l + 1)) {
tre[a].ls = tre[a << 1].ls + tre[(a << 1) | 1].ls;
}
else {
tre[a].ls = tre[a << 1].ls;
}
}
else {
tre[a].v = tre[a << 1].v + tre[(a << 1) | 1].v;
tre[a].ls = tre[a << 1].ls;
tre[a].rs = tre[(a << 1) | 1].rs;
}
};
function<ll(int, int,int ,int,int)>query = [&](int l, int r,int a,int L,int R) {
//cout << l << ' ' << r << ' ' << a << ' ' << L << ' ' << R << ' ' << tre[a].v << '\n';
if (l >= L && r <= R)return tre[a].v;
int mid = (l + r) >> 1;
if (L <= mid && R > mid) {
ll kase1 = query(l, mid, a << 1, L, R);
ll kase2 = query(mid + 1, r, (a << 1) | 1, L, R);
ll kase;
// cout << "find::" << tre[a<<1].rs<<' '<<tre[(a<<1)|1].ls<<' '<<kase1<<' '<<kase2<<endl;
// cout << tre[(a << 1) | 1].ln << ' ' << tre[(a << 1) | 1].rn << endl;
if (tre[(a << 1)].rn <= tre[(a << 1) | 1].ln) {
kase=kase1+kase2+ (min(tre[a << 1].rs,(ll)(mid-L+1))*min(tre[(a << 1) | 1].ls,(ll)(R-mid)));
}
else {
kase = kase1 + kase2;
}
return kase;
}
else {
if (L <= mid) {
return query(l, mid, a << 1, L, R);
}
else {
return query(mid + 1, r, (a << 1) | 1, L, R);
}
}
};
while (m--) {
int op;
cin >> op;
if (op == 1) {
int pos, t;
cin >> pos >> t;
update(pos, t, 1, n, 1);
}
else {
int l, r;
cin >> l >> r;
cout << query(1,n,1,l, r) << '\n';
}
}
return 0;
}