2151: 集训难度
Submit Page Summary Time Limit: 1 Sec Memory Limit: 512 Mb Submitted: 55 Solved: 12
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
题目看起来不难,根本模板题一样的(但是我WA了一个早上),就是简单地写一个线段树,他同时具备染色操作和增加某个数的操作。
思路:
设置两个tag,tag1表示当前区间要全部加上tag1, tag2表示当前区间全被染成tag2,传递tag1的时候,如果tag1存在,那么如果子节点的tag2存在,那么直接往tag2上加,如果没有,就往子节点的tag1上加,传tag2的时候,子节点的tag1直接就清掉,然后tag2就继承下来。
AC代码:
//假如加上一个变化操作 ,就把加法操作的tag清空
//如何下传被清空的tag标记?
//难以实现
//那么选择直接把tag1加到tag2上 ?
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define md(l,r) (l+r)>>1
#define rson(x) x<<1|1
#define lson(x) x<<1
#define endl '\n'
#define sc(x) scanf("%d",&x)
using namespace std;
typedef long long LL;
const int size=1e5+5;
const int inf=0x3f3f3f3f;
struct node{
int l,r;
LL sum,tag;
LL tag2;
bool flag ;
}tree[size<<2];
void build(int k,int l,int r,int v)
{
tree[k].l=l,tree[k].r=r;
if(l==r)
{
tree[k].sum=v;
tree[k].tag=0;
tree[k].tag2=inf;
tree[k].flag=0;
return ;
}
int mid=md(l,r);
build(rson(k),mid+1,r,v);
build(lson(k),l,mid,v);
tree[k].sum=tree[lson(k)].sum+tree[rson(k)].sum;
tree[k].tag=0;
tree[k].tag2=inf;
tree[k].flag=0;
}
void change(int k)
{
if(tree[k].l!=tree[k].r)
{
int ls=lson(k),rs=rson(k);
tree[rs].sum+=(tree[rs].r-tree[rs].l+1)*tree[k].tag;
tree[ls].sum+=(tree[ls].r-tree[ls].l+1)*tree[k].tag;
if(tree[ls].tag2==inf)
tree[ls].tag+=tree[k].tag;
else tree[ls].tag2+=tree[k].tag;
if(tree[rs].tag2==inf)
tree[rs].tag+=tree[k].tag;
else tree[rs].tag2+=tree[k].tag;
tree[ls].flag=1;
tree[rs].flag=1;
}
tree[k].tag=0;
tree[k].flag=0;
}
void change2(int k)
{
if(tree[k].l!=tree[k].r)
{
int ls=lson(k),rs=rson(k);
tree[ls].sum=tree[k].tag2*(tree[ls].r-tree[ls].l+1);
tree[rs].sum=(tree[rs].r-tree[rs].l+1)*tree[k].tag2;
tree[ls].tag2=tree[k].tag2;
tree[rs].tag2=tree[k].tag2;
tree[ls].tag=0;
tree[rs].tag=0;
}
tree[k].tag2=inf;
}
void add2(int k,int l,int r,LL x)
{
if(tree[k].flag) change(k);
if(tree[k].tag2!=inf) change2(k);
if(tree[k].l==l&&tree[k].r==r)
{
tree[k].sum=x*(r-l+1);
tree[k].tag2=x;
tree[k].tag=0;
return ;
}
int mid=md(tree[k].l,tree[k].r);
if(l>=mid+1) add2(rson(k),l,r,x);
else if(r<=mid) add2(lson(k),l,r,x);
else add2(lson(k),l,mid,x),add2(rson(k),mid+1,r,x);
tree[k].sum=tree[lson(k)].sum+tree[rson(k)].sum;
}
void add(int k,int l,int r,LL x)
{
if(tree[k].flag) change(k);
if(tree[k].tag2!=inf) change2(k);
tree[k].sum+=x*(r-l+1);
if(l==tree[k].l&&r==tree[k].r)
{
tree[k].tag+=x;
tree[k].flag=1;
return ;
}
int mid=md(tree[k].l,tree[k].r);
if(l>=mid+1)
{
add(rson(k),l,r,x);
}
else if(r<=mid)
{
add(lson(k),l,r,x);
}
else
{
add(lson(k),l,mid,x),add(rson(k),mid+1,r,x);
}
tree[k].sum=tree[lson(k)].sum+tree[rson(k)].sum;
}
LL query(int k,int l,int r)
{
LL ans=0;
if(tree[k].flag) change(k);
if(tree[k].tag2!=inf) change2(k);
if(l==tree[k].l&&r==tree[k].r)
{
return tree[k].sum;
}
int mid=md(tree[k].l,tree[k].r);
if(l>=mid+1)
{
ans=query(rson(k),l,r);
}
else if(r<=mid)
{
ans=query(lson(k),l,r);
}
else
{
ans=query(lson(k),l,mid)+query(rson(k),mid+1,r);
}
return ans;
}
int main()
{
int n,m,v0;
while(~scanf("%d%d%d",&n,&m,&v0))
{
build(1,1,n+1,v0);
while(m--)
{
int op;
scanf("%d",&op);
if(op==0)
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
add(1,l,r,v);
}
else if(op==1)
{
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
add2(1,l,r,v);
}
else if(op==2)
{
int l,r;
sc(l),sc(r);
cout<<query(1,l,r)<<endl;
}
}
}
return 0;
}
/*
4 9 2
0 1 3 2
2 1 1
1 2 4 2
2 1 1
0 1 4 1
2 1 1
2 2 2
2 3 3
2 4 4
*/
/**********************************************************************
Problem: 2151
User: 0908170402
Language: C++
Result: AC
Time:352 ms
Memory:17648 kb
**********************************************************************/