题目描述
Description
有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]的最小值
输入描述
Input Description
第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述
输出描述
Output Description
对于所有的sum、max、min询问,一行输出一个答案
样例输入
Sample Input
10 6
3 9 2 8 1 7 5 0 4 6
add 4 9 4
set 2 6 2
add 3 8 2
sum 2 10
max 1 7
min 3 6
样例输出
Sample Output
49
11
4
数据范围及提示
Data Size & Hint
10%:1<n,m<=10
30%:1<n,m<=10000
100%:1<n,m<=100000
保证中间结果在long long(C/C++)、int64(pascal)范围内
思路;
有两个标记一个add一个set,我们肯定是优先处理set操作,如果当前点被set标记了,那么之前的add标记也会被清空,所以当进行set操作是必须要清空add标记。
题目没给 c 的范围,那么我们假定他为 -1e9 < c < 1e9 ,那么也就是有可能存在等于0和负数的情况,所以set标记的初始化可以选定为 -1e16;
为社么感觉写过。。。
实现代码;
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid ll m = (l + r) >> 1 const ll M = 1e5 + 10; const ll inf = 1e16+10; ll sum[M<<2],Set[M<<2],mx[M<<2],add[M<<2],mn[M<<2]; ll a[M]; void pushup(ll rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; mx[rt] = max(mx[rt<<1],mx[rt<<1|1]); mn[rt] = min(mn[rt<<1],mn[rt<<1|1]); } void pushdown(ll l,ll r,ll rt){ if(Set[rt]!=-inf){ mid; sum[rt<<1] = Set[rt]*(m-l+1); sum[rt<<1|1] = Set[rt]*(r-m); mx[rt<<1] = mx[rt<<1|1] = Set[rt]; mn[rt<<1] = mn[rt<<1|1] = Set[rt]; Set[rt<<1] = Set[rt<<1|1] = Set[rt]; add[rt<<1] = add[rt<<1|1] = 0; Set[rt] = -inf; } if(add[rt]){ mid; sum[rt<<1] += add[rt]*(m-l+1); sum[rt<<1|1] += add[rt]*(r-m); mx[rt<<1] += add[rt]; mx[rt<<1|1] += add[rt]; mn[rt<<1] += add[rt]; mn[rt<<1|1] += add[rt]; add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; add[rt] = 0; } } void build(ll l,ll r,ll rt){ Set[rt] = -inf; add[rt] = 0; if(l == r){ sum[rt] = mx[rt] = mn[rt] = a[l]; Set[rt] = -inf;add[rt] = 0; return ; } mid; build(lson); build(rson); pushup(rt); } void update(ll L,ll R,ll op,ll c,ll l,ll r,ll rt){ if(L <= l&&R >= r){ if(op == 1){ sum[rt] = (r-l+1)*c; mx[rt] = mn[rt] = Set[rt] = c; add[rt] = 0; return ; } else{ sum[rt] += (r-l+1)*c; mx[rt] += c; add[rt] += c; mn[rt] += c; return ; } } pushdown(l,r,rt); mid; if(L <= m) update(L,R,op,c,lson); if(R > m) update(L,R,op,c,rson); pushup(rt); } ll query_sum(ll L,ll R,ll l,ll r,ll rt){ if(L <= l&&R >= r){ return sum[rt]; } pushdown(l,r,rt); mid; ll ret = 0; if(L <= m) ret += query_sum(L,R,lson); if(R > m) ret += query_sum(L,R,rson); return ret; } ll query_max(ll L,ll R,ll l,ll r,ll rt){ if(L <= l&&R >= r){ return mx[rt]; } pushdown(l,r,rt); mid; ll ret = -inf; if(L <= m) ret = max(ret,query_max(L,R,lson)); if(R > m) ret = max(ret,query_max(L,R,rson)); return ret; } ll query_min(ll L,ll R,ll l,ll r,ll rt){ if(L <= l&&R >= r){ return mn[rt]; } pushdown(l,r,rt); mid,ret = inf; if(L <= m) ret = min(ret,query_min(L,R,lson)); if(R > m) ret = min(ret,query_min(L,R,rson)); return ret; } char s[100]; int main(){ ll n,l,r,c,q; scanf("%lld%lld",&n,&q); for(ll i = 1;i <= n;i ++) scanf("%lld",&a[i]); build(1,n,1); while(q--){ scanf("%s",s); scanf("%lld%lld",&l,&r); if(s[0] == 'a'){ scanf("%lld",&c); update(l,r,0,c,1,n,1); } else if(s[0] == 's'&&s[1] == 'e'){ scanf("%lld",&c); update(l,r,1,c,1,n,1); } else if(s[0] == 's'&&s[1] == 'u'){ printf("%lld\n",query_sum(l,r,1,n,1)); } else if(s[0] == 'm'&&s[1] == 'a'){ printf("%lld\n",query_max(l,r,1,n,1)); } else { printf("%lld\n",query_min(l,r,1,n,1)); } } return 0; }