题意:
有n个数和5种操作
add a b c:把区间[a,b]内的所有数都增加c
set a b c:把区间[a,b]内的所有数都设为c
sum a b:查询区间[a,b]的区间和
max a b:查询区间[a,b]的最大值
min a b:查询区间[a,b]的最小值
解题思路:
- 线段树的的修改和设置
- 设置两个值 set 和 add 分别表示设置和增加的延迟标记。用标记 f 这个区间上次的操作(1 表示上一次对这个区间的操作为设置,0 表示上次对这个区间操作为增加)。
- debug太难了。 QwQ
AC代码:
using namespace std;
typedef long long ll;
const int N = 200005;
int n,m,a[N];
struct ST
{
int l,r;
bool f;
ll add,sum,set,minval,maxval;
}t[4*N];
char op[5];
void build(int p,int l,int r){
t[p].l = l,t[p].r = r;
if(l==r){
t[p].sum = a[l];
t[p].minval = t[p].maxval = a[l];
t[p].f = t[p].set = t[p].add = 0;
return;
}
int mid = (l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].sum = t[p*2].sum + t[p*2+1].sum;
t[p].minval = min(t[p*2].minval,t[p*2+1].minval);
t[p].maxval = max(t[p*2].maxval,t[p*2+1].maxval);
t[p].f = t[p].set = 0;
return ;
}
void spread(int p){
if(t[p].l == t[p].r) return;
if(t[p].f == 1){
t[p*2].sum = t[p].set * (t[2*p].r - t[2*p].l +1);
t[p*2+1].sum = t[p].set * (t[p*2+1].r - t[2*p+1].l +1);
t[p*2].minval = t[p*2].maxval = t[p*2+1].minval = t[p*2+1].maxval = t[p].set;
t[p*2].add = t[p*2+1].add = 0;
t[p*2].f = t[p*2+1].f = 1; t[p].f = 0;
t[p*2].set = t[p*2+1].set = t[p].set; t[p].set = 0;
t[p].add = 0; // !!
}
if(t[p].add){
if(t[2*p].set) t[p*2].set += t[p].add;
else t[p*2].add += t[p].add;
if(t[p*2+1].set) t[p*2+1].set += t[p].add;
else t[p*2+1].add += t[p].add;
t[p*2].sum += t[p].add * (t[p*2].r - t[p*2].l +1);
t[p*2+1].sum += t[p].add * (t[p*2+1].r - t[p*2+1].l +1);
t[p*2].maxval += t[p].add; t[p*2].minval += t[p].add;
t[p*2+1].minval += t[p].add; t[p*2+1].maxval += t[p].add;
t[p].add = 0;
}
}
void change(int p,int l,int r,int d){
spread(p);
if(l <= t[p].l && t[p].r <= r){
if(t[p].set) t[p].set += d;
else t[p].add += d;
t[p].sum += (long long )d*(t[p].r - t[p].l+1);
t[p].maxval += d; t[p].minval += d;
return;
}
int mid = (t[p].r + t[p].l)/2;
if(mid >= l) change(p*2,l,r,d);
if(r > mid) change(p*2+1,l,r,d);
t[p].minval = min(t[p*2].minval,t[p*2+1].minval);
t[p].maxval = max(t[p*2].maxval,t[p*2+1].maxval);
t[p].sum = t[p*2].sum+t[p*2+1].sum;
return ;
}
void setval(int p,int l,int r,int d){
if(l <= t[p].l && t[p].r <= r){
t[p].sum = (long long )d*(t[p].r - t[p].l +1);
t[p].set = d;
t[p].minval = t[p].maxval = d;
t[p].add = 0;
t[p].f = 1;
return;
}
spread(p);
int mid = (t[p].l+t[p].r)/2;
if(l <= mid) setval(2*p,l,r,d);
if(r > mid) setval(p*2+1,l,r,d);
t[p].sum = t[2*p].sum + t[2*p+1].sum;
t[p].minval = min(t[p*2].minval,t[p*2+1].minval);
t[p].maxval = max(t[p*2].maxval,t[p*2+1].maxval);
return;
}
ll ask(int p,int l,int r){
if(l <= t[p].l && t[p].r <= r){
if(op[0] == 's') return t[p].sum;
else if(op[1] == 'a') return t[p].maxval;
else return t[p].minval;
}
spread(p);
int mid = (t[p].l + t[p].r)/2;
if(op[0] == 's'){
ll res = 0;
if(l <= mid) res += ask(2*p,l,r);
if(r > mid) res += ask(2*p+1,l,r);
return res;
}else if(op[1] == 'a'){
ll res = -1e18;
if(l <= mid) res = max(res,ask(2*p,l,r));
// cout << res << endl;
if(r > mid) res = max(res,ask(2*p+1,l,r));
// cout << res << endl << endl;
return res;
}else{
ll res = 1e18;
if(l<=mid) res = min(ask(2*p,l,r),res);
if(r >mid) res = min(res,ask(2*p+1,l,r));
return res;
}
}
int main(int argc, char const *argv[])
{
while(~scanf("%d%d",&n,&m)){
rep(i,1,n) scanf("%d",&a[i]);
build(1,1,n);
int a,b,d;
rep(i,1,m){
scanf("%s%d%d",op,&a,&b);
if(op[1] == 'e'){
scanf("%d",&d);
setval(1,a,b,d);
}else if(op[1] == 'd'){
scanf("%d",&d);
change(1,a,b,d);
}else{
printf("%lld\n",ask(1,a,b));
}
}
}
return 0;
}