1. 程式人生 > >codevs 4927 線段樹練習5 線段樹基本操作模板

codevs 4927 線段樹練習5 線段樹基本操作模板

-1 nbsp sca clock wrap 數據 span sam cloc

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)範圍內

----------------------------------------------------------------------------------------------------------------

重新溫習了一遍線段樹的一些基本操作,並把以前寫過的代碼重寫了一遍。

區間修改(增加和重設)和查詢(和,最大/小值)

為了同時實現這兩個區間修改的操作,需要給每段區間分別打上兩個標記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 線段樹基本操作模板