线段树lazy标记2
2017-12-19 16:22
211 查看
Description
给定一个正整数序列A,要求支持以下操作:
1):ADD a b c 表示在[a,b]上加上一个常数C。
2):COVER a b c 把[a,b]整体赋值为一个常数K。
3):QUERY a b 查询[a,b]的sum。
Input
第一行两个正整数n、m,n表示序列长度,m表示操作数。
第二行n个正整数,第i表示Ai的大小。
接下来的m行,每行有且仅有一种操作,具体和题目描述一致。
n,m<=100000,其他权值都<=50000,小心爆int。
Output
对于每个询问操作,输出答案。
Sample Input
10 10
17 18 16 12 13 7 13 6 11 20
QUERY 5 6
QUERY 2 7
ADD 1 6 13
QUERY 4 10
ADD 2 5 18
COVER 2 8 11
ADD 6 9 5
QUERY 8 8
ADD 6 9 18
QUERY 5 7
Sample Output
20
79
121
16
79
HINT
思路
记录3个标记:icoveri表示这个点是否在下传标记后被覆盖。coveri表示这个点被覆盖成了什么值。sumi表示这个点被增加了多少。下传时先考虑cover的下传,再考虑sum的下传。注意每次一个点被覆盖后这个点的sum值都要被赋成0。
代码
给定一个正整数序列A,要求支持以下操作:
1):ADD a b c 表示在[a,b]上加上一个常数C。
2):COVER a b c 把[a,b]整体赋值为一个常数K。
3):QUERY a b 查询[a,b]的sum。
Input
第一行两个正整数n、m,n表示序列长度,m表示操作数。
第二行n个正整数,第i表示Ai的大小。
接下来的m行,每行有且仅有一种操作,具体和题目描述一致。
n,m<=100000,其他权值都<=50000,小心爆int。
Output
对于每个询问操作,输出答案。
Sample Input
10 10
17 18 16 12 13 7 13 6 11 20
QUERY 5 6
QUERY 2 7
ADD 1 6 13
QUERY 4 10
ADD 2 5 18
COVER 2 8 11
ADD 6 9 5
QUERY 8 8
ADD 6 9 18
QUERY 5 7
Sample Output
20
79
121
16
79
HINT
思路
记录3个标记:icoveri表示这个点是否在下传标记后被覆盖。coveri表示这个点被覆盖成了什么值。sumi表示这个点被增加了多少。下传时先考虑cover的下传,再考虑sum的下传。注意每次一个点被覆盖后这个点的sum值都要被赋成0。
代码
#include <cstdio> const int maxn=100000; long long a[maxn+10]; struct segment_tree { long long val[(maxn<<2)+10],sum[(maxn<<2)+10],cover[(maxn<<2)+10]; int icover[(maxn<<2)+10]; inline int updata(int now)//更新这个点的val { val[now]=val[now<<1]+val[now<<1|1]; return val[now]; } inline int pushdown(int now,int left,int right)//下传标记 { int mid=(left+right)>>1; if(icover[now])//如果这个点被cover过,下传cover标记 { icover[now]=0; cover[now<<1]=cover[now]; sum[now<<1]=0;//注意sum标记要赋成0 val[now<<1]=cover[now]*(mid-left+1); cover[now<<1|1]=cover[now]; sum[now<<1|1]=0; val[now<<1|1]=cover[now]*(right-mid); icover[now<<1]=icover[now<<1|1]=1;//表示被覆盖过 } sum[now<<1]+=sum[now];//下传sum标记 val[now<<1]+=sum[now]*(mid-left+1); sum[now<<1|1]+=sum[now]; val[now<<1|1]+=sum[now]*(right-mid); sum[now]=0; return 0; } int build(int now,int left,int right)//建树 { if(left==right) { icover[now]=0;//初始化 sum[now]=0; val[now]=a[left]; return 0; } int mid=(left+right)>>1; build(now<<1,left,mid); build(now<<1|1,mid+1,right); updata(now); return 0; } int rcover(int now,int left,int right,int askl,int askr,long long cval) //将一个区间[left,right]cover成cval { if((askl<=left)&&(right<=askr)) { icover[now]=1;//覆盖 cover[now]=cval; sum[now]=0;//注意 val[now]=cval*(right-left+1); return 0; } int mid=(left+right)>>1; pushdown(now,left,right); if(askl<=mid) { rcover(now<<1,left,mid,askl,askr,cval); } if(mid<askr) { rcover(now<<1|1,mid+1,right,askl,askr,cval); } updata(now); return 0; } int add(int now,int left,int right,int askl,int askr,long long cval) //将一个区间的值增加 { if((askl<=left)&&(right<=askr)) { sum[now]+=cval; val[now]+=cval*(right-left+1); return 0; } int mid=(left+right)>>1; pushdown(now,left,right); if(askl<=mid) { add(now<<1,left,mid,askl,askr,cval); } if(mid<askr) { add(now<<1|1,mid+1,right,askl,askr,cval); } updata(now); return 0; } long long getsum(int now,int left,int right,int askl,int askr) //求一段区间的和 { if((askl<=left)&&(right<=askr)) { return val[now]; } int mid=(left+right)>>1; long long res=0; pushdown(now,left,right); if(askl<=mid) { res+=getsum(now<<1,left,mid,askl,askr); } if(mid<askr) { res+=getsum(now<<1|1,mid+1,right,askl,askr); } return res; } }; segment_tree st; int n,m,aa,b; long long c; char s[10]; int main() { scanf("%d%d",&n,&m); for(register int i=1; i<=n; ++i) { scanf("%lld",&a[i]); } st.build(1,1,n); while(m--) { scanf("%s%d%d",s,&aa,&b); if(s[0]=='Q') { printf("%lld\n",st.getsum(1,1,n,aa,b)); } else if(s[0]=='C') { scanf("%lld",&c); st.rcover(1,1,n,aa,b,c); } else { scanf("%lld",&c); st.add(1,1,n,aa,b,c); } } return 0; }
相关文章推荐
- 线段树区间修改之双标记 【lazy两重标记并且分类讨论】
- 线段树的标记lazy_tag
- 线段树求区间最大值+区间更新+区间求和+lazy标记
- WikiOI 1217 借教室 (线段树lazy标记)(95分)
- POJ 3237 Tree (树链剖分 路径剖分 线段树的lazy标记)
- POJ 2777 count color(线段树,lazy标记)
- 线段树区间更新模板(lazy延迟标记)(1698)
- zoj1610(线段树成段覆盖,lazy标记)
- hdu 1698 线段树区间更新入门(lazy标记)
- 还教室(线段树lazy标记)
- 线段树模板(lazy标记)ZOJ 3686
- 专题 线段树 E(区间更新,使用lazy标记)
- hdu1698(线段树成段更新+lazy标记)
- 线段树入门 以HDU 4325为例(未离散化,也没lazy标记)
- [模板] - 线段树 - Lazy标记 - 单点/区间更新 - 模板
- Pku oj 3468 A Simple Problem with Integers(线段树Lazy标记)
- POJ 3468-A Simple Problem with Integers(线段树_区间更新+lazy标记)
- HDU1698 Just a Hook 【线段树】+【成段更新】+【lazy标记】
- hdu 1698 poj 3468 线段树 成段更新(lazy标记)
- poj 3468 A Simple Problem with Integers(线段树成段更新,延迟标记,Lazy)