http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2151
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
Hint
Source
某场noip模拟题
Author
lfw
思路:基本上是裸的线段树题目吧,涉及到区间修改和区间覆盖,因此我们用两个lazy标记就好了。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct node
{
int l,r;
ll sum,lazy1,lazy2;
};
node tree[400005];
int n,m;
ll v0;
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
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 down1(int i)//区间修改
{
tree[i<<1].lazy1+=tree[i].lazy1;
tree[i<<1|1].lazy1+=tree[i].lazy1;
tree[i<<1].sum+=tree[i].lazy1*(tree[i<<1].r-tree[i<<1].l+1);
tree[i<<1|1].sum+=tree[i].lazy1*(tree[i<<1|1].r-tree[i<<1|1].l+1);
tree[i].lazy1=0;
}
void down2(int i)//区间覆盖
{
tree[i<<1].lazy2=tree[i].lazy2;
tree[i<<1|1].lazy2=tree[i].lazy2;
tree[i<<1].lazy1=tree[i<<1|1].lazy1=0;
tree[i<<1].sum=tree[i].lazy2*(tree[i<<1].r-tree[i<<1].l+1);
tree[i<<1|1].sum=tree[i].lazy2*(tree[i<<1|1].r-tree[i<<1|1].l+1);
tree[i].lazy2=INF;
}
void update(int p,int i,int l,int r,ll v)
{
if(tree[i].l==l&&tree[i].r==r)
{
if(p==0)//区间修改
{
tree[i].lazy1+=v;
tree[i].sum+=(r-l+1)*v;
}
else if(p==1)//区间覆盖
{
tree[i].lazy2=v;
tree[i].lazy1=0;//很重要
tree[i].sum=(r-l+1)*v;
}
return ;
}
if(tree[i].lazy2!=INF)
down2(i);
if(tree[i].lazy1)
down1(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
update(p,i<<1,l,r,v);
else if(l>=mid+1)
update(p,i<<1|1,l,r,v);
else
{
update(p,i<<1,l,mid,v);
update(p,i<<1|1,mid+1,r,v);
}
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
ll query(int i,int l,int r)
{
if(tree[i].l==l&&tree[i].r==r)
return tree[i].sum;
if(tree[i].lazy2!=INF)
down2(i);
if(tree[i].lazy1)
down1(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid)
return query(i<<1,l,r);
else if(l>=mid+1)
return query(i<<1|1,l,r);
else
return query(i<<1,l,mid)+query(i<<1|1,mid+1,r);
}
int main()
{
scanf("%d %d %lld",&n,&m,&v0);
build(1,1,n);
int p,l,r;
ll v;
while(m--)
{
scanf("%d %d %d",&p,&l,&r);
if(p==0||p==1)
{
scanf("%lld",&v);
update(p,1,l,r,v);
}
else if(p==2)
printf("%lld\n",query(1,l,r));
}
return 0;
}