线段树。query:区间求和
update 有两种操作:区间加减 和 区间取相反数。
所以 lazy 标记也有两个。
所以需要注意的是,一个结点不能同时存在两种标记,因为不知道是先加后乘还是先乘后加。要 pushDown 下去
ps:其实本来最近想专心弄 DP 来着,可是数据结构作业是线段树,所以就学了一下。。。
#include <cstdio>
using namespace std;
const int maxn = 110000;
typedef long long LL;
LL addv[maxn<<2], sg[maxn<<2], sum[maxn<<2];
void pushUp(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void pushDown(int rt, int l, int r)
{
if(l == r) {
return ;
}
int m = (l + r) >> 1;
if(addv[rt]) {
int len = r - l + 1;
if(!~sg[rt<<1])
pushDown(rt<<1, l, m);
if(!~sg[rt<<1|1])
pushDown(rt<<1|1, m+1, r);
addv[rt<<1] += addv[rt];
addv[rt<<1|1] += addv[rt];
sum[rt<<1] += addv[rt] * (len - (len>>1));
sum[rt<<1|1] += addv[rt] * (len>>1);
addv[rt] = 0;
sg[rt] = 1;
} else if(!~sg[rt]) {
if(addv[rt<<1])
pushDown(rt<<1, l, m);
if(addv[rt<<1|1])
pushDown(rt<<1|1, m+1, r);
sg[rt<<1] *= -1;
sg[rt<<1|1] *= -1;
sum[rt<<1] *= -1;
sum[rt<<1|1] *= -1;
sg[rt] = 1;
addv[rt] = 0;
}
}
void build(int rt, int l, int r)
{
addv[rt] = 0;
sg[rt] = 1;
if(l == r) {
scanf("%lld", &sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(rt<<1, l, m);
build(rt<<1|1, m+1, r);
pushUp(rt);
}
LL query(int L, int R, int rt, int l, int r)
{
if(L <= l && r <= R)
return sum[rt];
pushDown(rt, l, r);
int m = (l + r) >> 1;
LL ret = 0;
if(L <= m) ret += query(L, R, rt<<1, l, m);
if(R > m) ret += query(L, R, rt<<1|1, m+1, r);
return ret;
}
void add(int L, int R, LL c, int rt, int l, int r)
{
pushDown(rt, l, r);
if(L <= l && r <= R) {
addv[rt] += c;
sum[rt] += (r - l + 1) * c;
return ;
}
int m = (l + r) >> 1;
if(L <= m) add(L, R, c, rt<<1, l, m);
if(R > m) add(L, R, c, rt<<1|1, m+1, r);
pushUp(rt);
}
void rev(int L, int R, int rt, int l, int r)
{
pushDown(rt, l, r);
if(L <= l && r <= R) {
sg[rt] *= -1;
sum[rt] *= -1;
return ;
}
int m = (l + r) >> 1;
if(L <= m) rev(L, R, rt<<1, l, m);
if(R > m) rev(L, R, rt<<1|1, m+1, r);
pushUp(rt);
}
int main()
{
int n;
while(~scanf("%d", &n)) {
int q;
build(1, 1, n);
scanf("%d", &q);
while(q--) {
char cmd[2];
scanf("%s", cmd);
if(cmd[0] == 'Q') {
int a, b;
scanf("%d%d", &a, &b);
printf("%lld\n", query(a, b, 1, 1, n));
} else if(cmd[0] == 'T') {
int a, b;
scanf("%d%d", &a, &b);
rev(a, b, 1, 1, n);
} else if(cmd[0] == 'A') {
int a, b;
LL c;
scanf("%d%d%lld", &a, &b, &c);
add(a, b, c, 1, 1, n);
}
}
}
return 0;
}