codevs 4927 线段树练习5 线段树基本操作模板
Posted lpl_bys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 4927 线段树练习5 线段树基本操作模板相关的知识,希望对你有一定的参考价值。
4927 线段树练习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]的最小值
第一行两个整数n,m,第二行n个整数表示这n个数的初始值
接下来m行操作,同题目描述
对于所有的sum、max、min询问,一行输出一个答案
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
49
11
4
10%:1<n,m<=10
30%:1<n,m<=10000
100%:1<n,m<=100000
保证中间结果在long long(C/C++)、int64(pascal)范围内
----------------------------------------------------------------------------------------------------------------
重新温习了一遍线段树的一些基本操作,并把以前写过的代码重写了一遍。
区间修改(增加和重设)和查询(和,最大/小值)
为了同时实现这两个区间修改的操作,需要给每段区间分别打上两个标记tag和set,一个记录add修改,另一个记录set修改
add修改就直接累加tag,set修改除了需要把set标记覆盖为新值之外,还需要把tag清零,具体实现看代码
需要注意的是pushdown(下传)的时候应该是set在前 add在后,对应前面对标记的操作(因为前面是遇到set操作时就会清空tag,所以应该是先set后tag,即先重设后增加),顺序不能颠倒
AC代码:
1 #include<stdio.h> 2 #include<iostream> 3 #include<stdlib.h> 4 #include<string.h> 5 #define maxn 2333333 6 using namespace std; 7 struct node{ 8 int l,r; 9 int tag,set; 10 long long sum; 11 int ma,mi; 12 }; 13 node tr[maxn]; 14 int read(); 15 void build(int,int,int); 16 void fma(int,int,int); 17 void add(int,int,int,int); 18 void putdownsum(int); 19 void putdownset(int); 20 int n,m,sts[100010],o; 21 long long ans; 22 char s1[23]={"add"},s2[23]={"set"},s3[23]={"sum"},s4[23]={"max"}; 23 bool flag,bl[maxn]; 24 int main(){ 25 memset(bl,0,sizeof(bl)); 26 n=read(),m=read(); 27 for(int i=1;i<=n;i++) sts[i]=read(); 28 build(1,n,1); 29 for(int i=1;i<=m;i++){ 30 char s[23]; 31 memset(s,0,sizeof(s)); 32 scanf(" %s",s); 33 if(!memcmp(s,s1,3)){ 34 int a=read(),b=read(),c=read(); 35 flag=true; 36 add(a,b,c,1); 37 } 38 else if(!memcmp(s,s2,3)){ 39 int a=read(),b=read(),c=read(); 40 flag=false; 41 add(a,b,c,1); 42 } 43 else if(!memcmp(s,s3,3)){ 44 int a=read(),b=read(); 45 ans=0;o=3; 46 fma(a,b,1); 47 printf("%lld\n",ans); 48 } 49 else if(!memcmp(s,s4,3)){ 50 int a=read(),b=read(); 51 ans=0;o=1; 52 fma(a,b,1); 53 printf("%lld\n",ans); 54 } 55 else{ 56 int a=read(),b=read(); 57 ans=1e15;o=2; 58 fma(a,b,1); 59 printf("%lld\n",ans); 60 } 61 } 62 return 0; 63 } 64 #define lson k<<1 65 #define rson k<<1|1 66 void pushup(int k){ 67 tr[k].sum=tr[lson].sum+tr[rson].sum; 68 tr[k].ma=max(tr[lson].ma,tr[rson].ma); 69 tr[k].mi=min(tr[lson].mi,tr[rson].mi); 70 } 71 void build(int l,int r,int k){ 72 tr[k].l=l;tr[k].r=r; 73 if(l==r){ 74 tr[k].sum=tr[k].ma=tr[k].mi=sts[l]; 75 return; 76 } 77 int mid=(l+r)>>1; 78 build(l,mid,lson); 79 build(mid+1,r,rson); 80 pushup(k); 81 } 82 void add(int l,int r,int x,int k){ 83 if(l<=tr[k].l&&tr[k].r<=r){ 84 if(flag){ 85 tr[k].tag+=x; 86 tr[k].sum+=(tr[k].r-tr[k].l+1)*x; 87 tr[k].ma+=x; 88 tr[k].mi+=x; 89 } 90 else{ 91 bl[k]=1; 92 tr[k].tag=0; 93 tr[k].sum=(tr[k].r-tr[k].l+1)*x; 94 tr[k].set=tr[k].ma=tr[k].mi=x; 95 } 96 return; 97 } 98 if(bl[k]) putdownset(k); 99 if(tr[k].tag) putdownsum(k); 100 int mid=(tr[k].l+tr[k].r)>>1; 101 if(l<=mid) add(l,r,x,lson); 102 if(mid<r) add(l,r,x,rson); 103 pushup(k); 104 } 105 void putdownset(int k){ 106 tr[lson].set=tr[k].set;bl[lson]=1; 107 tr[rson].set=tr[k].set;bl[rson]=1; 108 tr[lson].sum=(tr[lson].r-tr[lson].l+1)*tr[k].set; 109 tr[rson].sum=(tr[rson].r-tr[rson].l+1)*tr[k].set; 110 tr[lson].ma=tr[k].set;tr[rson].ma=tr[k].set; 111 tr[lson].mi=tr[k].set;tr[rson].mi=tr[k].set; 112 tr[lson].tag=0;tr[rson].tag=0; 113 tr[k].set=0;bl[k]=0; 114 } 115 void putdownsum(int k){ 116 tr[lson].tag+=tr[k].tag; 117 tr[rson].tag+=tr[k].tag; 118 tr[lson].sum+=(tr[lson].r-tr[lson].l+1)*tr[k].tag; 119 tr[rson].sum+=(tr[rson].r-tr[rson].l+1)*tr[k].tag; 120 tr[lson].ma+=tr[k].tag;tr[rson].ma+=tr[k].tag; 121 tr[lson].mi+=tr[k].tag;tr[rson].mi+=tr[k].tag; 122 tr[k].tag=0; 123 } 124 void fma(int l,int r,int k){ 125 if(l<=tr[k].l&&tr[k].r<=r){ 126 if(o==1) ans=ans>tr[k].ma?ans:tr[k].ma; 127 else if(o==2) ans=ans>tr[k].mi?tr[k].mi:ans; 128 else ans+=tr[k].sum; 129 return; 130 } 131 if(bl[k]) putdownset(k); 132 if(tr[k].tag) putdownsum(k); 133 int mid=(tr[k].r+tr[k].l)>>1; 134 if(l<=mid) fma(l,r,lson); 135 if(mid<r) fma(l,r,rson); 136 } 137 int read(){ 138 int an=0,f=1;char c=getchar(); 139 while(‘0‘>c||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} 140 while(‘0‘<=c&&c<=‘9‘)an=an*10+c-48,c=getchar();return an*f; 141 }
以上是关于codevs 4927 线段树练习5 线段树基本操作模板的主要内容,如果未能解决你的问题,请参考以下文章