题面

UOJ

Sol

玄学,不会势能分析

所以

维护区间最大最小值

把开根变成区间减法

如果最大值开根后的变化量和最小值的相等,就直接打个减法\(lazy\)

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
# define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout)
using namespace std;
typedef long long ll;
const int _(1e5 + 5); IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} int n, m;
struct Segment{
ll mx, mn, tag, sum;
} T[_ << 2]; IL void Build(RG int x, RG int l, RG int r){
if(l == r){
T[x].mn = T[x].mx = T[x].sum = Input();
return;
}
RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
Build(ls, l, mid), Build(rs, mid + 1, r);
T[x].mn = min(T[ls].mn, T[rs].mn);
T[x].mx = max(T[ls].mx, T[rs].mx);
T[x].sum = T[ls].sum + T[rs].sum;
} IL void Adjust(RG int x, RG ll v, RG int l, RG int r){
T[x].tag += v, T[x].mx += v, T[x].mn += v, T[x].sum += 1LL * (r - l + 1) * v;
} IL void Pushdown(RG int x, RG int l, RG int mid, RG int r){
if(T[x].tag == 0) return;
Adjust(x << 1, T[x].tag, l, mid);
Adjust(x << 1 | 1, T[x].tag, mid + 1, r);
T[x].tag = 0;
} IL void Modify2(RG int x, RG int l, RG int r, RG int L, RG int R, RG ll v){
if(L <= l && R >= r){
Adjust(x, v, l, r);
return;
}
RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
Pushdown(x, l, mid, r);
if(L <= mid) Modify2(ls, l, mid, L, R, v);
if(R > mid) Modify2(rs, mid + 1, r, L, R, v);
T[x].mn = min(T[ls].mn, T[rs].mn);
T[x].mx = max(T[ls].mx, T[rs].mx);
T[x].sum = T[ls].sum + T[rs].sum;
} IL void Modify1(RG int x, RG int l, RG int r, RG int L, RG int R){
RG ll v1 = sqrt(T[x].mn), v2 = sqrt(T[x].mx);
v1 -= T[x].mn, v2 -= T[x].mx;
if(v1 == v2){
Modify2(x, l, r, L, R, v1);
return;
}
RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
Pushdown(x, l, mid, r);
if(L <= mid) Modify1(ls, l, mid, L, R);
if(R > mid) Modify1(rs, mid + 1, r, L, R);
T[x].mn = min(T[ls].mn, T[rs].mn);
T[x].mx = max(T[ls].mx, T[rs].mx);
T[x].sum = T[ls].sum + T[rs].sum;
} IL ll Query(RG int x, RG int l, RG int r, RG int L, RG int R){
if(L <= l && R >= r) return T[x].sum;
RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1;
RG ll ans = 0;
Pushdown(x, l, mid, r);
if(L <= mid) ans = Query(ls, l, mid, L, R);
if(R > mid) ans += Query(rs, mid + 1, r, L, R);
T[x].mn = min(T[ls].mn, T[rs].mn);
T[x].mx = max(T[ls].mx, T[rs].mx);
T[x].sum = T[ls].sum + T[rs].sum;
return ans;
} int main(RG int argc, RG char *argv[]){
n = Input(), m = Input(), Build(1, 1, n);
while(m--){
RG int op = Input(), l = Input(), r = Input(), v;
if(op == 1) v = Input(), Modify2(1, 1, n, l, r, v);
else if(op == 2) Modify1(1, 1, n, l, r);
else printf("%lld\n", Query(1, 1, n, l, r));
}
return 0;
}
05-11 20:26