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\n",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\n",ans); 138 } 139 else 140 { 141 scanf("%d%d",&x,&y); 142 ans=1e17; 143 query(1,3); 144 printf("%lld\n",ans); 145 } 146 } 147 }