题解:P12448 [COTS 2025] 观草 / Trava 题解
Claire0918 · · 题解
考虑阶梯化贡献,即求
如果对于
我们考虑对于
我们考虑如何计算初始的答案。设
考虑
我们发现这些项中有一些和
时间复杂度
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 5e5 + 10;
int n, q;
int a[maxn], pl[maxn], pr[maxn];
long long d1[maxn], d2[maxn], res[maxn];
namespace BIT{
long long tree1[maxn], tree2[maxn];
inline int lbw(int x){
return x & -x;
}
inline void add(int x, int k){
for (int i = x; i; tree1[i] += k, tree2[i] += x * k, i -= lbw(i));
}
inline long long query(int x){
long long res = 0;
for (int i = x; i <= n; res += tree2[i] - (x - 1) * tree1[i], i += lbw(i));
return res;
}
}
using namespace BIT;
namespace segtree{
struct{
int l, r, val;
} tree[maxn << 2];
inline void build(int index, int l, int r){
tree[index].l = l, tree[index].r = r;
if (l == r){
return tree[index].val = a[l], void();
}
const int mid = l + r >> 1;
build(index << 1, l, mid), build(index << 1 | 1, mid + 1, r), tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
}
inline void modify(int index, int x, int k){
if (tree[index].l == tree[index].r){
return tree[index].val = k, void();
}
const int mid = tree[index].l + tree[index].r >> 1;
modify(index << 1 | x > mid, x, k), tree[index].val = max(tree[index << 1].val, tree[index << 1 | 1].val);
}
inline pair<int, int> calc(int index, int x, int k){
if (tree[index].l == tree[index].r){
return make_pair(0, 0);
}
const int mid = tree[index].l + tree[index].r >> 1;
const pair<int, int> tmp = calc(index << 1 | x > mid, x, k);
if (x <= mid){
return tree[index << 1 | 1].val >= k && !tmp.second ? make_pair(tmp.first, index << 1 | 1) : tmp;
}else{
return tree[index << 1].val >= k && !tmp.first ? make_pair(index << 1, tmp.second) : tmp;
}
}
inline int fnd1(int index, int k){
if (tree[index].l == tree[index].r){
return tree[index].l;
}
const int mid = tree[index].l + tree[index].r >> 1;
return tree[index << 1 | 1].val < k ? fnd1(index << 1, k) : fnd1(index << 1 | 1, k);
}
inline int fnd2(int index, int k){
if (tree[index].l == tree[index].r){
return tree[index].l;
}
const int mid = tree[index].l + tree[index].r >> 1;
return tree[index << 1].val < k ? fnd2(index << 1 | 1, k) : fnd2(index << 1, k);
}
}
using namespace segtree;
int main(){
scanf("%d %d", &n, &q), a[0] = a[n + 1] = 2e9;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
for (pl[i] = i - 1; pl[i] && a[pl[i]] < a[i]; pl[i] = pl[pl[i]]);
}
build(1, 0, n + 1);
for (int i = n; i; i--){
for (pr[i] = i + 1; pr[i] && a[pr[i]] <= a[i]; pr[i] = pr[pr[i]]);
}
for (int i = 1; i <= n; i++){
pl[i]++, pr[i]--;
long long x = i - pl[i] + 1, y = pr[i] - i + 1;
x > y && (swap(x, y), 1538), d2[1] += a[i], d2[x] -= a[i], d1[x] += a[i] * x, d1[y] += y * a[i], d1[x + y + 1] -= (x + y) * a[i], d2[y] -= a[i], d2[x + y + 1] += a[i];
}
for (int i = 1; i <= n; i++){
d1[i] += d1[i - 1], d2[i] += d2[i - 1], res[i] = d1[i] + d2[i] * i;
}
while (q--){
char op[10];
int x;
scanf("%s %d", op, &x);
if (op[0] == '?'){
printf("%lld\n", res[x] + query(x));
}else{
modify(1, x, ++a[x]);
const pair<int, int> pos = calc(1, x, a[x]);
const int l = fnd1(pos.first, a[x]) + 1, r = fnd2(pos.second, a[x]) - 1;
add(r - l + 1, 1), add(x - l, -1), add(r - x, -1);
}
}
return 0;
}