题意
区间加减,区间开根,区间求和
题解
线段树维护区间和,整个区间是否为同一个数,区间加写lazy标记。
具体实现看代码。
代码
// by ztx
#include<cmath>
#include<cstdio>
typedef long long ll;
#define maxn 100010LL
#define maxt 400010LL
int n, m, s[maxn];
ll sum[maxt];
bool all_same[maxt];
ll the_same_num[maxt];
ll lazy[maxt];
void maintain(int o) {
sum[o] = sum[o<<1]+sum[o<<1|1];
if (all_same[o<<1] && all_same[o<<1|1] && the_same_num[o<<1]==the_same_num[o<<1|1])
all_same[o] = 1, the_same_num[o] = the_same_num[o<<1];
else all_same[o] = the_same_num[o] = 0;
}
void clear(int o, int leftlen, int rightlen) {
sum[o<<1] += 1LL*lazy[o]*leftlen, sum[o<<1|1] += 1LL*lazy[o]*rightlen;
if (all_same[o<<1]) the_same_num[o<<1] += lazy[o];
lazy[o<<1] += lazy[o];
if (all_same[o<<1|1]) the_same_num[o<<1|1]+=lazy[o];
lazy[o<<1|1] += lazy[o];
lazy[o] = 0LL;
}
void build(int o,int L,int R) {
int M = (L+R)/2;
if (L == R) {
all_same[o] = 1, lazy[o] = 0, the_same_num[o] = sum[o] = s[M];
return;
}
build(o<<1,L,M), build(o<<1|1,M+1,R);
all_same[o] = the_same_num[o] = lazy[o] = 0, maintain(o);
}
int ql, qr;
ll qa;
void insert(int o,int L,int R) {
int M = (L+R)/2;
if (ql<=L && R<=qr) {
sum[o] += 1LL*qa*(R-L+1);
if (all_same[o]) the_same_num[o] += qa;
lazy[o] += qa;
return;
}
if (lazy[o] && L!=R) clear(o,M-L+1,R-M);
if (ql <= M) insert(o<<1,L,M);
if (qr > M) insert(o<<1|1,M+1,R);
maintain(o);
}
void modify(int o,int L,int R) {
int M = (L+R)/2;
if (ql<=L && R<=qr && all_same[o]) {
ll lastnum = the_same_num[o];
ll newnum = floor(sqrt(the_same_num[o]));
the_same_num[o] = newnum;
sum[o] = the_same_num[o]*(R-L+1);
lazy[o] += newnum-lastnum;
return;
}
if (lazy[o] && L!=R) clear(o,M-L+1,R-M);
if (ql <= M) modify(o<<1,L,M);
if (qr > M) modify(o<<1|1,M+1,R);
maintain(o);
}
void query(int o,int L,int R) {
int M = (L+R)/2;
if (ql<=L && R<=qr) {
qa += sum[o]; return;
}
if (lazy[o] && L!=R) clear(o,M-L+1,R-M);
if (ql <= M) query(o<<1,L,M);
if (qr > M) query(o<<1|1,M+1,R);
}
inline void Add(int L,int R,int X) {
ql = L, qr = R, qa = X;
insert(1,1,n);
}
inline void Sqrt(int L,int R) {
ql = L, qr = R;
modify(1,1,n);
}
inline ll Query(int L,int R) {
ql = L, qr = R, qa = 0;
query(1,1,n);
return qa;
}
int main() {
int T, i, mode, l, r, X;
scanf("%d",&T);
while (T --> 0) {
scanf("%d%d", &n, &m);
for (i = 1; i <= n; i ++ ) scanf("%d",&s[i]);
build(1,1,n);
while (m --> 0) {
scanf("%d%d%d",&mode, &l, &r);
if (mode == 1) scanf("%d",&X), Add(l,r,X);
if (mode == 2) Sqrt(l,r);
if (mode == 3) printf("%lld\n",Query(l,r));
}
}
return 0;
}