4927 线段树练习5
题目描述 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)范围内
PS:由于数据6出错导致某些人只有90分,已于2016.5.13修正。
出题人在此对两位90分的用户表示诚挚的歉意
好恶心的一道题
这道题特殊在set操作
对于这个操作,我们需要增加两个变量来维护,一个维护这个区间是否被修改,一个维护被修改成了多少
特别注意不能只维护被修改成了多少(会有0的情况)
在下传标记的时候,需要先下传set标记,再下传add标记
因为我们在设置set标记的时候已经把add标记置为0
如果此时add标记不为0,就说明这个标记一定是在set标记设置之后设置的
再注意一下细节就可以了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #define LL long long 6 #define ls k<<1 7 #define rs k<<1|1 8 using namespace std; 9 const LL MAXN=400400; 10 const LL INF =0x7fffff; 11 inline void read(LL &n) 12 { 13 char c=getchar();n=0;bool flag=0; 14 while(c<'0'||c>'9') c=='-'?flag=1,c=getchar():c=getchar(); 15 while(c>='0'&&c<='9') n=n*10+c-48,c=getchar();flag==1?n=-n:n=n; 16 } 17 struct node 18 { 19 LL l,r,w,Max,Min,Set,Add; 20 bool V; 21 }tree[MAXN]; 22 LL n,m; 23 LL ans=0; 24 inline void update(LL k) 25 { 26 tree[k].w=tree[ls].w+tree[rs].w; 27 tree[k].Max=max(tree[ls].Max,tree[rs].Max); 28 tree[k].Min=min(tree[ls].Min,tree[rs].Min); 29 } 30 void Build_Tree(LL ll,LL rr,LL k) 31 { 32 tree[k].l=ll;tree[k].r=rr; 33 if(tree[k].l==tree[k].r) 34 { 35 read(tree[k].w); 36 tree[k].Max=tree[k].w; 37 tree[k].Min=tree[k].w; 38 return ; 39 } 40 LL mid=tree[k].l+tree[k].r>>1; 41 Build_Tree(ll,mid,ls); 42 Build_Tree(mid+1,rr,rs); 43 update(k); 44 } 45 void down(LL k) 46 { 47 if(tree[k].V) 48 { 49 tree[ls].Add=0; 50 tree[ls].V=1; 51 tree[ls].w=(tree[ls].r-tree[ls].l+1)*tree[k].Set; 52 tree[ls].Max=tree[ls].Min=tree[ls].Set=tree[k].Set; 53 54 tree[rs].Add=0; 55 tree[rs].V=1; 56 tree[rs].w=(tree[rs].r-tree[rs].l+1)*tree[k].Set; 57 tree[rs].Max=tree[rs].Min=tree[rs].Set=tree[k].Set; 58 59 tree[k].Set=tree[k].V=0; 60 } 61 if(tree[k].Add) 62 { 63 tree[ls].w+=(tree[ls].r-tree[ls].l+1)*tree[k].Add; 64 tree[ls].Add+=tree[k].Add; 65 tree[ls].Max+=tree[k].Add; 66 tree[ls].Min+=tree[k].Add; 67 68 tree[rs].w+=(tree[rs].r-tree[rs].l+1)*tree[k].Add; 69 tree[rs].Add+=tree[k].Add; 70 tree[rs].Max+=tree[k].Add; 71 tree[rs].Min+=tree[k].Add; 72 tree[k].Add=0; 73 } 74 75 } 76 void Interval_Add(LL k,LL ll,LL rr,LL val) 77 { 78 if(ll<=tree[k].l&&tree[k].r<=rr) 79 { 80 tree[k].w+=(tree[k].r-tree[k].l+1)*val; 81 tree[k].Add+=val; 82 tree[k].Max+=val; 83 tree[k].Min+=val; 84 return ; 85 } 86 if(tree[k].Add||tree[k].V) down(k); 87 LL mid=tree[k].r+tree[k].l>>1; 88 if(ll<=mid) Interval_Add(ls,ll,rr,val); 89 if(rr>mid) Interval_Add(rs,ll,rr,val); 90 update(k); 91 } 92 void Interval_Change(LL k,LL ll,LL rr,LL val) 93 { 94 if(ll<=tree[k].l&&tree[k].r<=rr) 95 { 96 tree[k].Max=tree[k].Min=val; 97 tree[k].Set=val;tree[k].V=1; 98 tree[k].w=(tree[k].r-tree[k].l+1)*val; 99 tree[k].Add=0; 100 return ; 101 } 102 if(tree[k].Add||tree[k].V) down(k); 103 LL mid=tree[k].r+tree[k].l>>1; 104 if(ll<=mid) Interval_Change(ls,ll,rr,val); 105 if(rr>mid) Interval_Change(rs,ll,rr,val); 106 update(k); 107 } 108 void Interval_Sum(LL k,LL ll,LL rr) 109 { 110 if(ll<=tree[k].l&&tree[k].r<=rr) 111 { 112 ans+=tree[k].w; 113 return ; 114 } 115 if(tree[k].Add||tree[k].V) down(k); 116 LL mid=tree[k].r+tree[k].l>>1; 117 if(ll<=mid) Interval_Sum(ls,ll,rr); 118 if(rr>mid) Interval_Sum(rs,ll,rr); 119 } 120 void Interval_Max(LL k,LL ll,LL rr) 121 { 122 if(ll<=tree[k].l&&tree[k].r<=rr) 123 { 124 ans=max(ans,tree[k].Max); 125 return ; 126 } 127 if(tree[k].Add||tree[k].V) down(k); 128 LL mid=tree[k].r+tree[k].l>>1; 129 if(ll<=mid) Interval_Max(ls,ll,rr); 130 if(rr>mid) Interval_Max(rs,ll,rr); 131 } 132 void Interval_Min(LL k,LL ll,LL rr) 133 { 134 if(ll<=tree[k].l&&tree[k].r<=rr) 135 { 136 ans=min(ans,tree[k].Min); 137 return ; 138 } 139 if(tree[k].Add||tree[k].V) down(k); 140 LL mid=tree[k].r+tree[k].l>>1; 141 if(ll<=mid) Interval_Min(ls,ll,rr); 142 if(rr>mid) Interval_Min(rs,ll,rr); 143 } 144 int main() 145 { 146 read(n);read(m); 147 Build_Tree(1,n,1); 148 for(LL i=1;i<=m;i++) 149 { 150 char how[5]; 151 scanf("%s",how); 152 if(how[0]=='a')//区间加 153 { 154 LL x,y,val;read(x);read(y);read(val); 155 Interval_Add(1,x,y,val); 156 } 157 else if(how[0]=='s'&&how[1]=='e')//区间赋值 158 { 159 LL x,y,val;read(x);read(y);read(val); 160 Interval_Change(1,x,y,val); 161 } 162 else if(how[0]=='s'&&how[1]=='u')//区间求和 163 { 164 LL x,y;read(x);read(y);ans=0; 165 Interval_Sum(1,x,y); 166 printf("%lld\n",ans); 167 } 168 else if(how[0]=='m'&&how[1]=='a')//区间最大值 169 { 170 LL x,y;read(x);read(y);ans=0; 171 Interval_Max(1,x,y); 172 printf("%lld\n",ans); 173 } 174 else if(how[0]=='m'&&how[1]=='i')// 区间最小值 175 { 176 LL x,y;read(x);read(y);ans=INF; 177 Interval_Min(1,x,y); 178 printf("%lld\n",ans); 179 } 180 } 181 return 0; 182 }
作者:自为风月马前卒
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。