codevs4927 线段树练习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)范围内
正解:线段树
解题报告:
这就是传说中的线段树综合题,所有标记都有。
注意一点,就是我的执行顺序是先add标记下传,然后才是set标记下传,但下传过程中set可以覆盖add。开始我一直WA,后来才发现了一个错误,就是我先执行的add,那么,如果当前结点上此时既有set又有add,那么只能说明add一定是在set之后执行的,不然执行set的时候add早已经下传,所以我可以考虑直接把add的值直接加在set上去,就可以避免有一部分add没有发挥作用。害得我调试了半个小时。
1 //It is made by jump~ 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #include <algorithm> 8 #include <ctime> 9 #include <vector> 10 #include <queue> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long LL; 15 #define RG register 16 const int MAXN = 100011; 17 int n,m,ql,qr; 18 LL val,ans,inf; 19 char ch[10]; 20 struct node{ 21 int l,r; 22 LL minl,maxl,sum,add,set; 23 bool flag; 24 }a[MAXN*3]; 25 26 inline LL getint(){RG LL w=0,q=0; char c=getchar();while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar();while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;} 27 28 inline void update(RG int root){ 29 RG int lc=root*2,rc=lc+1; a[root].maxl=max(a[lc].maxl,a[rc].maxl); 30 a[root].sum=a[lc].sum+a[rc].sum; a[root].minl=min(a[lc].minl,a[rc].minl); 31 } 32 33 inline void build(RG int root,RG int l,RG int r){ 34 a[root].l=l; a[root].r=r; 35 if(l==r) { a[root].minl=a[root].maxl=a[root].sum=getint(); return ; } 36 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 37 build(lc,l,mid); build(rc,mid+1,r); update(root); 38 } 39 40 inline void pushdown(int root,int l,int r){ 41 if(!a[root].flag) return ; if(l==r) { a[root].flag=false; a[root].set=0; return ; } 42 int lc=root*2,rc=lc+1; int mid=(l+r)/2; 43 a[lc].set=a[rc].set=a[root].set; a[root].add=a[lc].add=a[rc].add=0; 44 a[lc].maxl=a[rc].maxl=a[lc].minl=a[rc].minl=a[root].set; 45 a[lc].sum=(LL)(mid-l+1)*a[root].set; a[rc].sum=(LL)(r-mid)*a[root].set; a[root].sum=a[lc].sum+a[rc].sum; 46 a[lc].flag=a[rc].flag=true; 47 a[root].set=0; a[root].flag=false; 48 } 49 50 inline void pushdown_add(RG int root,RG int l,RG int r){ 51 if(l==r) { a[root].add=0; return ; } if(a[root].add==0) return ; 52 53 if(a[root].flag){ a[root].set+=a[root].add; a[root].add=0; return ; }//至关重要,因为add打在set的后面,这就意味着相当于我们可以把set设的值变大一点 54 55 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; a[lc].add+=a[root].add; a[rc].add+=a[root].add; 56 a[lc].minl+=a[root].add; a[lc].maxl+=a[root].add; a[rc].minl+=a[root].add; a[rc].maxl+=a[root].add; 57 a[lc].sum+=a[root].add*(LL)(mid-l+1); a[rc].sum+=a[root].add*(LL)(r-mid); 58 a[root].add=0; a[root].sum=a[lc].sum+a[rc].sum; 59 } 60 61 inline void add(RG int root,RG int l,RG int r){ 62 pushdown_add(root,l,r); pushdown(root,l,r); 63 if(ql<=l && r<=qr) { a[root].add+=val; a[root].maxl+=val; a[root].minl+=val; a[root].sum+=val*(LL)(r-l+1); return ; } 64 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; if(ql<=mid) add(lc,l,mid); if(qr>mid) add(rc,mid+1,r); 65 update(root); 66 } 67 68 inline void update_set(RG int root,RG int l,RG int r){ 69 if(ql<=l && r<=qr) { a[root].flag=true; a[root].minl=a[root].maxl=a[root].set=val; a[root].add=0; a[root].sum=(LL)(r-l+1)*val; return ; } 70 pushdown_add(root,l,r); pushdown(root,l,r); 71 RG int mid=(l+r)/2;RG int lc=root*2,rc=lc+1; 72 if(ql<=mid) update_set(lc,l,mid); if(qr>mid) update_set(rc,mid+1,r); update(root); 73 } 74 75 inline void query_sum(RG int root,RG int l,RG int r){ 76 pushdown_add(root,l,r); pushdown(root,l,r); 77 if(ql<=l && r<=qr){ ans+=a[root].sum; return ; } 78 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 79 if(ql<=mid) query_sum(lc,l,mid); if(qr>mid) query_sum(rc,mid+1,r); update(root); 80 } 81 82 inline void query_max(RG int root,RG int l,RG int r){ 83 pushdown_add(root,l,r); pushdown(root,l,r); 84 if(ql<=l && r<=qr){ ans=max(a[root].maxl,ans); return ; } 85 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 86 if(ql<=mid) query_max(lc,l,mid); if(qr>mid) query_max(rc,mid+1,r); update(root); 87 } 88 89 inline void query_min(RG int root,RG int l,RG int r){ 90 pushdown_add(root,l,r); pushdown(root,l,r); 91 if(ql<=l && r<=qr){ ans=min(a[root].minl,ans); return ; } 92 RG int mid=(l+r)/2; RG int lc=root*2,rc=lc+1; 93 if(ql<=mid) query_min(lc,l,mid); if(qr>mid) query_min(rc,mid+1,r); update(root); 94 } 95 96 inline void work(){ 97 n=getint(); m=getint(); build(1,1,n); inf=1; for(RG int i=1;i<=62;i++) inf*=2; 98 while(m--) { 99 scanf("%s",ch); 100 if(ch[0]=='a') { ql=getint(); qr=getint(); val=getint(); add(1,1,n); } 101 else if(ch[0]=='s' && ch[1]=='e') { ql=getint(); qr=getint(); val=getint(); update_set(1,1,n); } 102 else if(ch[0]=='s' && ch[1]=='u') { ql=getint(); qr=getint(); ans=0; query_sum(1,1,n); printf("%lld\n",ans); } 103 else if(ch[0]=='m' && ch[1]=='a') { ql=getint(); qr=getint(); ans=-inf; query_max(1,1,n); printf("%lld\n",ans); } 104 else{ ql=getint(); qr=getint(); ans=inf; query_min(1,1,n); printf("%lld\n",ans); } 105 } 106 } 107 108 int main() 109 { 110 work(); 111 return 0; 112 }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!