Codeves 4279 线段树练习5

有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)范围内

题解:线段树基本操作,区间修改,区间加,区间求最大,最小值;

参考代码:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define N 100001
  4 using namespace std;
  5 int n,m,x,y;
  6 long long z;
  7 long long ans;
  8 struct node
  9 {
 10     int l,r,siz;
 11     long long set,add,minn,maxn,sum;
 12     bool v;
 13 }tr[N*4]; 
 14 void up(int k)
 15 {
 16     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
 17     tr[k].maxn=max(tr[k<<1].maxn,tr[k<<1|1].maxn);
 18     tr[k].minn=min(tr[k<<1].minn,tr[k<<1|1].minn);
 19 }
 20 void build(int k,int l,int r)
 21 {
 22     tr[k].l=l; tr[k].r=r; tr[k].siz=r-l+1;
 23     if(l==r) 
 24     {
 25         scanf("%d",&x);
 26         tr[k].sum=tr[k].maxn=tr[k].minn=x; 
 27         return ;
 28     }
 29     int mid=l+r>>1;
 30     build(k<<1,l,mid);
 31     build(k<<1|1,mid+1,r);
 32     up(k);
 33 }
 34 void down_set(int k)
 35 {
 36     int l=k<<1,r=k<<1|1;
 37     tr[l].add=tr[r].add=0;
 38     tr[l].set=tr[r].set=tr[k].set;
 39     tr[l].v=tr[r].v=true;
 40     tr[l].maxn=tr[r].maxn=tr[l].minn=tr[r].minn=tr[k].set;
 41     tr[l].sum=tr[l].siz*tr[k].set;
 42     tr[r].sum=tr[r].siz*tr[k].set;
 43     tr[k].v=tr[k].set=0;
 44 }
 45 void down_add(int k)
 46 {
 47     int l=k<<1,r=k<<1|1;
 48     tr[l].maxn+=tr[k].add;
 49     tr[r].maxn+=tr[k].add;
 50     tr[l].minn+=tr[k].add;
 51     tr[r].minn+=tr[k].add;
 52     tr[l].sum+=tr[l].siz*tr[k].add;
 53     tr[r].sum+=tr[r].siz*tr[k].add;
 54     tr[l].add+=tr[k].add; 
 55     tr[r].add+=tr[k].add;
 56     tr[k].add=0;
 57 }
 58 void addd(int k)
 59 {
 60     if(tr[k].l>=x&&tr[k].r<=y)
 61     {
 62         tr[k].add+=z;
 63         tr[k].maxn+=z;
 64         tr[k].minn+=z;
 65         tr[k].sum+=z*tr[k].siz;
 66         return;
 67     }
 68     if(tr[k].v) down_set(k);
 69     if(tr[k].add) down_add(k);
 70     int mid=tr[k].l+tr[k].r>>1;
 71     if(x<=mid) addd(k<<1);
 72     if(y>mid) addd(k<<1|1);
 73     up(k);
 74 } 
 75 void sett(int k)
 76 {
 77     if(tr[k].l>=x&&tr[k].r<=y)
 78     {
 79         tr[k].maxn=tr[k].minn=z;
 80         tr[k].set=z; tr[k].v=true;
 81         tr[k].sum=z*tr[k].siz;
 82         tr[k].add=0;
 83         return;
 84     }
 85     if(tr[k].v) down_set(k);
 86     if(tr[k].add) down_add(k);
 87     int mid=tr[k].l+tr[k].r>>1;
 88     if(x<=mid) sett(k<<1);
 89     if(y>mid) sett(k<<1|1);
 90     up(k);
 91 }
 92 void query(int k,int w)
 93 {
 94     if(tr[k].l>=x&&tr[k].r<=y)
 95     {
 96         if(w==1) ans+=tr[k].sum;
 97         else if(w==2) ans=max(ans,tr[k].maxn);
 98         else ans=min(ans,tr[k].minn); 
 99         return;
100     }
101     if(tr[k].v) down_set(k);
102     if(tr[k].add) down_add(k);
103     int mid=tr[k].l+tr[k].r>>1;
104     if(x<=mid) query(k<<1,w);
105     if(y>mid) query(k<<1|1,w);
106 }
107 int main()
108 {
109     scanf("%d%d",&n,&m);
110     build(1,1,n);
111     char ch[8];
112     while(m--)
113     {
114         scanf("%s",ch);
115         if(ch[0]=='a')
116         {
117             scanf("%d%d%lld",&x,&y,&z);
118             addd(1);
119         }
120         else if(ch[1]=='e')
121         {
122             scanf("%d%d%lld",&x,&y,&z);
123             sett(1);
124         }
125         else if(ch[1]=='u')
126         {
127             scanf("%d%d",&x,&y);
128             ans=0;
129             query(1,1);
130             printf("%lld
",ans);
131         }
132         else if(ch[1]=='a')
133         {
134             scanf("%d%d",&x,&y);
135             ans=-1;
136             query(1,2);
137             printf("%lld
",ans);
138         }
139         else
140         {
141             scanf("%d%d",&x,&y);
142             ans=1e17;
143             query(1,3);
144             printf("%lld
",ans);
145          } 
146     }
147 }
View Code
原文地址:https://www.cnblogs.com/csushl/p/9498471.html