支持将某一区间设为x,将某一区间加x,查询区间的和。

题目为 小明学求和II


 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #define mn 100001
 5 #define INF -1000001
 6 using namespace std;
 7 
 8 int n,m,b[mn],t,L,R,c;
 9 long long sum[30*mn],add[30*mn],set[30*mn];
10 
11 void buildtree(int k,int l,int r){
12     set[k]=INF;
13     int mid=(l+r)/2;
14     if (l==r) sum[k]=set[k]=b[l];
15     else{
16         buildtree(2*k,l,mid);
17         buildtree(2*k+1,mid+1,r);
18         sum[k]=sum[2*k]+sum[2*k+1];
19     }
20 }
21 
22 inline void pushdown(int k,int l,int r){
23     int mid=(l+r)/2;
24     if (r==l) return;
25     if (set[k]!=INF){
26         set[2*k]=set[2*k+1]=set[k];
27         add[2*k]=add[2*k+1]=0;
28         set[k]=INF;
29     }
30     add[2*k]+=add[k];
31     add[2*k+1]+=add[k];
32     add[k]=0;
33 }
34 
35 inline void maintain(int k,int l,int r){
36     if (set[k]!=INF) sum[k]=(set[k]+add[k])*(r-l+1);
37     else sum[k]=sum[2*k]+sum[2*k+1]+add[k]*(r-l+1);
38 }
39 
40 void updateadd(int k,int l,int r){
41     int mid=(l+r)/2;
42     if (L<=l && R>=r) add[k]+=c;
43     else{
44         pushdown(k,l,r);
45         if (L<=mid) updateadd(2*k,l,mid);else maintain(2*k,l,mid);
46         if (R>mid) updateadd(2*k+1,mid+1,r);else maintain(2*k+1,mid+1,r);
47     }
48     maintain(k,l,r);
49 }
50 
51 void updateset(int k,int l,int r){
52     int mid=(l+r)/2;
53     if (L<=l && R>=r){
54         set[k]=c;
55         add[k]=0;
56     }else{
57         pushdown(k,l,r);
58         if (L<=mid) updateset(2*k,l,mid);else maintain(2*k,l,mid);
59         if (R>mid) updateset(2*k+1,mid+1,r);else maintain(2*k+1,mid+1,r);
60     }
61     maintain(k,l,r);
62 }
63 
64 long long query(int k,int l,int r){
65     long long ans=0;
66     int mid=(l+r)/2;
67     if (L<=l && R>=r) return sum[k];
68     else if (set[k]!=INF) return (long long)(set[k]+add[k])*(min(R,r)-max(L,l)+1);
69     else{
70         if (L<=mid) ans+=query(2*k,l,mid);
71         if (R>mid) ans+=query(2*k+1,mid+1,r);
72         ans+=add[k]*(min(R,r)-max(L,l)+1);
73         return ans;
74     }
75 }
76 
77 int main(){
78     scanf("%d%d",&n,&m);
79     for (int i=1;i<=n;i++) scanf("%d",&b[i]);
80     buildtree(1,1,n);
81     for (int i=1;i<=m;i++){
82         scanf("%d",&t);
83         if (t==1){
84             scanf("%d%d%d",&L,&R,&c);
85             updateadd(1,1,n);
86         }else if (t==2){
87             scanf("%d%d%d",&L,&R,&c);
88             updateset(1,1,n);
89         }else{
90             scanf("%d%d",&L,&R);
91             printf("%lld\n",query(1,1,n));
92         }
93     }
94     return 0;
95 }