CodeForces 444C DZY Loves Colors
2014-07-15 21:10
447 查看
题意:
一段区间a一开始是1、2、3、4……n这样的 每次1操作可以将[l,r]覆盖成x 同时得到abs(a[i]-x)的价值 2操作查询[l,r]的价值
思路:
线段树 又是一道加深线段树理解的题
操作2是简单的求和 线段树基本操作 难点在操作1
用cov表示该区间的值(如果为0说明是混合区间) 用val表示该区间的价值和
那么在更新时就不仅仅是找到 tree[i].l==l&&tree[i].r==r 就停止了 而是继续向下递归 直到一段区间的cov>0才结束
之所以这么做是因为要将x覆盖到之前覆盖过的连续的区间(其实就是将以前混合的区间合并成一个) 这是更新val所必须的
但如此做了我们会发现val只计算到了更新过的位置 无法将这次更新down下去 那么就需要设置一个lazy标志
lazy记录该区间还没有被down下去的价值
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 101000
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
typedef __int64 ll;
int n,m;
struct node
{
int l,r,cov;
ll val,lazy;
}tree[N*4];
ll ans;
int abs(int x)
{
if(x<0) return -x;
return x;
}
void up(int i)
{
tree[i].val=tree[L(i)].val+tree[R(i)].val;
}
void down(int i)
{
if(tree[i].cov)
{
tree[L(i)].cov=tree[i].cov;
tree[R(i)].cov=tree[i].cov;
tree[i].cov=0;
}
if(tree[i].lazy)
{
tree[L(i)].lazy+=tree[i].lazy;
tree[L(i)].val+=tree[i].lazy*(tree[L(i)].r-tree[L(i)].l+1);
tree[R(i)].lazy+=tree[i].lazy;
tree[R(i)].val+=tree[i].lazy*(tree[R(i)].r-tree[R(i)].l+1);
tree[i].lazy=0;
}
}
void init(int l,int r,int i)
{
tree[i].l=l; tree[i].r=r; tree[i].val=tree[i].lazy=0;
if(l==r)
{
tree[i].cov=l;
return ;
}
int mid=(l+r)/2;
init(l,mid,L(i));
init(mid+1,r,R(i));
}
void solve(int i,int key)
{
if(tree[i].cov)
{
tree[i].lazy+=abs(key-tree[i].cov);
tree[i].val+=(ll)(abs(key-tree[i].cov))*(tree[i].r-tree[i].l+1);
tree[i].cov=key;
return ;
}
else
{
down(i);
solve(L(i),key);
solve(R(i),key);
up(i);
}
tree[i].cov=key;
}
void update(int l,int r,int i,int key)
{
if(tree[i].l==l&&tree[i].r==r)
{
solve(i,key);
return ;
}
down(i);
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid) update(l,r,L(i),key);
else if(l>mid) update(l,r,R(i),key);
else
{
update(l,mid,L(i),key);
update(mid+1,r,R(i),key);
}
up(i);
}
void query(int l,int r,int i)
{
if(tree[i].l==l&&tree[i].r==r)
{
ans+=tree[i].val;
return ;
}
down(i);
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid) query(l,r,L(i));
else if(l>mid) query(l,r,R(i));
else
{
query(l,mid,L(i));
query(mid+1,r,R(i));
}
up(i);
}
int main()
{
int p,l,r,w;
scanf("%d%d",&n,&m);
init(1,n,1);
while(m--)
{
scanf("%d%d%d",&p,&l,&r);
if(p==1)
{
scanf("%d",&w);
update(l,r,1,w);
}
else
{
ans=0;
query(l,r,1);
printf("%I64d\n",ans);
}
}
return 0;
}
一段区间a一开始是1、2、3、4……n这样的 每次1操作可以将[l,r]覆盖成x 同时得到abs(a[i]-x)的价值 2操作查询[l,r]的价值
思路:
线段树 又是一道加深线段树理解的题
操作2是简单的求和 线段树基本操作 难点在操作1
用cov表示该区间的值(如果为0说明是混合区间) 用val表示该区间的价值和
那么在更新时就不仅仅是找到 tree[i].l==l&&tree[i].r==r 就停止了 而是继续向下递归 直到一段区间的cov>0才结束
之所以这么做是因为要将x覆盖到之前覆盖过的连续的区间(其实就是将以前混合的区间合并成一个) 这是更新val所必须的
但如此做了我们会发现val只计算到了更新过的位置 无法将这次更新down下去 那么就需要设置一个lazy标志
lazy记录该区间还没有被down下去的价值
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 101000
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
typedef __int64 ll;
int n,m;
struct node
{
int l,r,cov;
ll val,lazy;
}tree[N*4];
ll ans;
int abs(int x)
{
if(x<0) return -x;
return x;
}
void up(int i)
{
tree[i].val=tree[L(i)].val+tree[R(i)].val;
}
void down(int i)
{
if(tree[i].cov)
{
tree[L(i)].cov=tree[i].cov;
tree[R(i)].cov=tree[i].cov;
tree[i].cov=0;
}
if(tree[i].lazy)
{
tree[L(i)].lazy+=tree[i].lazy;
tree[L(i)].val+=tree[i].lazy*(tree[L(i)].r-tree[L(i)].l+1);
tree[R(i)].lazy+=tree[i].lazy;
tree[R(i)].val+=tree[i].lazy*(tree[R(i)].r-tree[R(i)].l+1);
tree[i].lazy=0;
}
}
void init(int l,int r,int i)
{
tree[i].l=l; tree[i].r=r; tree[i].val=tree[i].lazy=0;
if(l==r)
{
tree[i].cov=l;
return ;
}
int mid=(l+r)/2;
init(l,mid,L(i));
init(mid+1,r,R(i));
}
void solve(int i,int key)
{
if(tree[i].cov)
{
tree[i].lazy+=abs(key-tree[i].cov);
tree[i].val+=(ll)(abs(key-tree[i].cov))*(tree[i].r-tree[i].l+1);
tree[i].cov=key;
return ;
}
else
{
down(i);
solve(L(i),key);
solve(R(i),key);
up(i);
}
tree[i].cov=key;
}
void update(int l,int r,int i,int key)
{
if(tree[i].l==l&&tree[i].r==r)
{
solve(i,key);
return ;
}
down(i);
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid) update(l,r,L(i),key);
else if(l>mid) update(l,r,R(i),key);
else
{
update(l,mid,L(i),key);
update(mid+1,r,R(i),key);
}
up(i);
}
void query(int l,int r,int i)
{
if(tree[i].l==l&&tree[i].r==r)
{
ans+=tree[i].val;
return ;
}
down(i);
int mid=(tree[i].l+tree[i].r)/2;
if(r<=mid) query(l,r,L(i));
else if(l>mid) query(l,r,R(i));
else
{
query(l,mid,L(i));
query(mid+1,r,R(i));
}
up(i);
}
int main()
{
int p,l,r,w;
scanf("%d%d",&n,&m);
init(1,n,1);
while(m--)
{
scanf("%d%d%d",&p,&l,&r);
if(p==1)
{
scanf("%d",&w);
update(l,r,1,w);
}
else
{
ans=0;
query(l,r,1);
printf("%I64d\n",ans);
}
}
return 0;
}
相关文章推荐
- Codeforces 444C DZY Loves Colors 线段树
- Codeforces 444C DZY Loves Colors(线段树)
- codeforces 444C DZY Loves Colors
- codeforces 444C. DZY Loves Colors (线段树)
- Codeforces 444C DZY Loves Colors
- Codeforces 444C DZY Loves Colors(线段树)
- 【线段树】 codeforces 444C DZY Loves Colors
- Codeforces 444C DZY Loves Colors 线段树区间更新
- CodeForces 444C - DZY Loves Colors(线段树)
- 【CodeForces】444C DZY Loves Colors 线段树
- Codeforces 444C DZY Loves Colors 水线段树
- Codeforces 444C DZY Loves Colors(线段树)
- Codeforces 444C DZY Loves Colors 线段树
- codeforces 444C DZY Loves Colors(线段树)
- codeforces - 444c DZY Loves Physics【水】
- Cf 444C DZY Loves Colors(线段树)
- CodeForces 444C. DZY Loves Physics(枚举+水题)
- Codeforces 444 C. DZY Loves Colors (线段树+剪枝)
- codeforces 444 C. DZY Loves Colors(线段树)
- CodeForces 445E DZY Loves Colors