codevs 4927 线段树练习5 线段树基本操作模板

Posted lpl_bys

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 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 线段树基本操作模板的主要内容,如果未能解决你的问题,请参考以下文章

codevs 4927 线段树练习5

codevs 4927 线段树练习5

codevs 4927 线段树练习5

分块试水--CODEVS4927 线段树练习5

线段树练习5(codevs 4927)

CodeVS 4927-线段树练习5