codevs 4927 線段樹練習5 線段樹基本操作模板
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 Input10 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)範圍內
----------------------------------------------------------------------------------------------------------------
重新溫習了一遍線段樹的一些基本操作,並把以前寫過的代碼重寫了一遍。
區間修改(增加和重設)和查詢(和,最大/小值)
為了同時實現這兩個區間修改的操作,需要給每段區間分別打上兩個標記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 線段樹基本操作模板