Description
小L正在组织acm暑假集训,但众所周知,暑假集训的萌新中有OI神犇,也有暑假才开始学算法的萌新,如果统一集训的难度,无法很好地让萌新们得到训练,所以小L想了一个办法,根据每次测试的情况,改变萌新们的集训难度。现在将萌新们编号为1到n,最初萌新们的集训难度为v0,测试后有两种操作,第一种是某一区间的萌新的集训难度同时提高,另一种是将某一段区间的萌新的集训难度变为同一个数,同时,Wells希望在某次调整难度之后,知道某一段区间的萌新的集训难度之和,由于小L比较鶸,他并不知道如何快速解决这个问题,你能帮帮他嘛?
Input
第一行三个数n,m,v0 表示有n名萌新和m次调整,初始时全部萌新的集训难度都为v0
第2~m+1行 每行三个数或四个数
0 x y v 表示把 [x,y]区间内的萌新的集训难度都增加v
1 x y v 表示把 [x,y]区间内的萌新的集训难度都变为v
2 x y表示询问[x,y]区间内萌新的集训难度之和
0<n,m<=10^5, |v|<=10^5
Output
每个询问一行,输出答案
Sample Input
3 5 0 0 1 3 1 1 2 3 2 2 1 1 2 2 2 2 2 3
Sample Output
1 2 4
wa,做这题心态爆炸,觉得自己改改应该就能过了,然后就两个小时过去了,然后就半个小时了,心想反正也没时间做其他的了,然后就爆零了。
这题其实是模板的线段树,只是有两个lazy标记,你pushdown的时候要考虑lazy之间的相互影响。设置两个lazy,lazy表示当前区间要全部加上lazy, lazy表示当前区间全被染成lazy,传递lazy的时候,如果lazy存在,那么如果子节点的lazy存在,那么直接往lazy2上加,如果没有,就往子节点的lazy1上加,传lazy2的时候,子节点的lazy1直接就清掉,然后lazy2就继承下来。
但是要注意pushdowm要放在最前面,每次change和query之前就要进行。还有lazy2要取一个取不到的值作为没有。
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=100005;
const double eps=1e-8;
const double pi=acos(-1.0);
const int MOD=10056;
int T,n,m,v0;
int x,y,v;
int flag;
struct Node
{
int l,r;
LL sum,lazy1,lazy2;
}tree[maxn<<2];
void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;tree[k].lazy1=0;tree[k].lazy2=INF;
if(l==r)
{
tree[k].sum=v0;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
void pushdown(int x)
{
if(tree[x].lazy2!=INF)
{
tree[x<<1].lazy1=0;
tree[x<<1|1].lazy1=0;
tree[x<<1].lazy2=tree[x].lazy2;
tree[x<<1|1].lazy2=tree[x].lazy2;
tree[x<<1].sum=tree[x].lazy2*(tree[x<<1].r-tree[x<<1].l+1);
tree[x<<1|1].sum=tree[x].lazy2*(tree[x<<1|1].r-tree[x<<1|1].l+1);
tree[x].lazy2=INF;
}
if(tree[x].lazy1!=0)
{
if(tree[x<<1].lazy2!=INF)
{
tree[x<<1].lazy1=0;
tree[x<<1].lazy2+=tree[x].lazy1;
tree[x<<1].sum=tree[x<<1].lazy2*(tree[x<<1].r-tree[x<<1].l+1);
}
else
{
tree[x<<1].lazy1+=tree[x].lazy1;
tree[x<<1].sum+=tree[x].lazy1*(tree[x<<1].r-tree[x<<1].l+1);
}
if(tree[x<<1|1].lazy2!=INF)
{
tree[x<<1|1].lazy1=0;
tree[x<<1|1].lazy2+=tree[x].lazy1;
tree[x<<1|1].sum=tree[x<<1|1].lazy2*(tree[x<<1|1].r-tree[x<<1|1].l+1);
}
else
{
tree[x<<1|1].lazy1+=tree[x].lazy1;
tree[x<<1|1].sum+=tree[x].lazy1*(tree[x<<1|1].r-tree[x<<1|1].l+1);
}
tree[x].lazy1=0;
}
}
void change(int k,int l,int r)
{
pushdown(k);
if(tree[k].l==l&&tree[k].r==r)
{
if(flag==0)
{
tree[k].lazy1+=v;
tree[k].sum+=v*(r-l+1);
}
else
{
tree[k].lazy2=v;
tree[k].lazy1=0;
tree[k].sum=v*(r-l+1);
}
return ;
}
if(tree[k].l==tree[k].r)
return;
int mid=(tree[k].l+tree[k].r)>>1;
if(mid>=r)
change(k<<1,l,r);
else if(mid<l)
change(k<<1|1,l,r);
else
{
change(k<<1,l,mid);
change(k<<1|1,mid+1,r);
}
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
LL query(int k,int l,int r)
{
pushdown(k);
LL maxx=0;
if(tree[k].l==l&&tree[k].r==r)
return tree[k].sum;
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
maxx+=query(k<<1,l,r);
else if(l>=mid+1)
maxx+=query(k<<1|1,l,r);
else
{
maxx+=query(k<<1,l,mid);
maxx+=query(k<<1|1,mid+1,r);
}
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
return maxx;
}
int main()
{
scanf("%d %d %d",&n,&m,&v0);
build(1,1,n);
while(m--)
{
scanf("%d",&flag);
if(flag==2)
{
scanf("%d %d",&x,&y);
// for(int i=1;i<=n;i++)
// printf("%d ",tree[i].sum);
// printf("\n");
printf("%lld\n",query(1,x,y));
}
else
{
scanf("%d %d %d",&x,&y,&v);
change(1,x,y);
}
}
return 0;
}
/*
9 4 8
0 2 8 4
0 7 7 3
1 1 3 7
2 3 8
*/
/**********************************************************************
Problem: 2151
User: jk1601zr
Language: C++
Result: AC
Time:260 ms
Memory:14524 kb
**********************************************************************/