codevs 4927 线段树练习5
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 4927 线段树练习5相关的知识,希望对你有一定的参考价值。
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 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标记。。
#include <cctype> #include <cstdio> #define N 100005 typedef long long LL; inline void read(LL &x) { bool f=0;register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()) if(ch==‘-‘) f=1; for(;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar()); x=f?-x:x; } bool fst[N<<2|1]; int n,m,siz[N<<2|1]; LL ans,maxv[N<<2|1],minv[N<<2|1],fplus[N<<2|1],fset[N<<2|1],val[N<<2|1]; inline LL max(LL a,LL b) {return a>b?a:b;} inline LL min(LL a,LL b) {return a>b?b:a;} inline void pushup(int k) { val[k]=val[k<<1]+val[k<<1|1]; maxv[k]=max(maxv[k<<1],maxv[k<<1|1]); minv[k]=min(minv[k<<1],minv[k<<1|1]); } void build(int k,int l,int r) { siz[k]=r-l+1; if(l==r) { read(val[k]); maxv[k]=minv[k]=val[k]; return; } LL mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); pushup(k); } void pushdown1(int k) { fplus[k<<1]=fplus[k<<1|1]=0; fset[k<<1]=fset[k<<1|1]=fset[k]; maxv[k<<1]=minv[k<<1]=fset[k]; maxv[k<<1|1]=minv[k<<1|1]=fset[k]; val[k<<1]=siz[k<<1]*fset[k]; val[k<<1|1]=siz[k<<1|1]*fset[k]; fst[k<<1]=fst[k<<1|1]=1; fset[k]=0;fst[k]=0; } void pushdown2(int k) { fplus[k<<1]+=fplus[k]; fplus[k<<1|1]+=fplus[k]; maxv[k<<1]+=fplus[k]; maxv[k<<1|1]+=fplus[k]; minv[k<<1]+=fplus[k]; minv[k<<1|1]+=fplus[k]; val[k<<1]+=fplus[k]*siz[k<<1]; val[k<<1|1]+=fplus[k]*siz[k<<1|1]; fplus[k]=0; } void modify(int k,int l,int r,int x,int y,LL v) { if(l>=x&&r<=y) { val[k]+=siz[k]*v; maxv[k]+=v; minv[k]+=v; fplus[k]+=v; return; } int mid=(l+r)>>1; if(fst[k]) pushdown1(k); if(fplus[k]) pushdown2(k); if(x<=mid) modify(k<<1,l,mid,x,y,v); if(y>mid) modify(k<<1|1,mid+1,r,x,y,v); pushup(k); } void change(int k,int l,int r,int x,int y,LL v) { if(l>=x&&r<=y) { val[k]=siz[k]*v; fplus[k]=0; maxv[k]=minv[k]=fset[k]=v; fst[k]=true; return; } int mid=(l+r)>>1; if(fst[k]) pushdown1(k); if(fplus[k]) pushdown2(k); if(x<=mid) change(k<<1,l,mid,x,y,v); if(y>mid) change(k<<1|1,mid+1,r,x,y,v); pushup(k); } void sum(int k,int l,int r,int x,int y) { if(l>=x&&r<=y) {ans+=val[k];return;} int mid=(l+r)>>1; if(fst[k]) pushdown1(k); if(fplus[k]) pushdown2(k); if(x<=mid) sum(k<<1,l,mid,x,y); if(y>mid) sum(k<<1|1,mid+1,r,x,y); pushup(k); } void Max(int k,int l,int r,int x,int y) { if(l>=x&&r<=y) {ans=max(ans,maxv[k]);return;} int mid=(l+r)>>1; if(fst[k]) pushdown1(k); if(fplus[k]) pushdown2(k); if(x<=mid) Max(k<<1,l,mid,x,y); if(y>mid) Max(k<<1|1,mid+1,r,x,y); pushup(k); } void Min(int k,int l,int r,int x,int y) { if(l>=x&&r<=y) {ans=min(ans,minv[k]);return;} int mid=(l+r)>>1; if(fst[k]) pushdown1(k); if(fplus[k]) pushdown2(k); if(x<=mid) Min(k<<1,l,mid,x,y); if(y>mid) Min(k<<1|1,mid+1,r,x,y); pushup(k); } int main(int argc,char *argv[]) { scanf("%d%d",&n,&m); build(1,1,n); char opt[10]; LL z; for(int x,y;m--;) { scanf("%s%d%d",opt,&x,&y); if(opt[0]==‘a‘) { read(z); modify(1,1,n,x,y,z); } else if(opt[0]==‘s‘) { if(opt[1]==‘e‘) read(z),change(1,1,n,x,y,z); else ans=0,sum(1,1,n,x,y),printf("%lld\n",ans); } else if(opt[0]==‘m‘) { if(opt[1]==‘i‘) ans=1e18,Min(1,1,n,x,y),printf("%lld\n",ans); else ans=-1e18,Max(1,1,n,x,y),printf("%lld\n",ans); } } return 0; }
以上是关于codevs 4927 线段树练习5的主要内容,如果未能解决你的问题,请参考以下文章