CodeForces 444C DZY Loves Colors题解

[题意]

     有n个气球,每个气球有一个颜色x,改变为y后,美丽值增加|x-y|.

     对一个序列有两种操作:

1.    把区间在[L,R]的颜色染成x.

2.   询问区间[L,R]的气球的美丽值总和.

n<=1e5,1<=x<=1e8.

[思路]

     区间更新,区间询问可以联想到线段树.

     只是更新的时候有点复杂:

     因为一个区间内的颜色不一定相同,无法一次性全部更新,那么我们就直接更新颜色相同的一块,把这一个区间都改变.再延迟更新,询问和更新的时候down下去.

     一直一直Wa的原因:

     在延迟更新的时候直接记录的是更新后的颜色,但是,这样是不行滴:一开始颜色是1,改为4,再改为2,答案是5,但是如果直接改成了2,答案就是1了.

当更新的区间越长,更新的时候就会进行地越深,访问的区间更多;

但更新后的区间的颜色是相同的,那么就会越有利于下次更新.两者的制约关系是不会超时的一个因素.

<span style="font-family:Comic Sans MS;font-size:18px;"><span style="font-family:Comic Sans MS;font-size:18px;">#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
inline void rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do{
        res=(res<<1)+(res<<3)+(c^48);
    }while(c=getchar(),c>=48);
}
inline void print(ll k){
    if(k==0)return ;
    print(k/10);
    putchar((k%10)^48);
}
inline void sc(ll k){
    print(k);
    if(k==0)putchar('0');
    putchar('\n');
}
const int M=1e5+5;
int  n,m;
struct node{
    ll b,c;//b为美丽值的和,c是颜色差的叠加(用于延迟更新).
    int f;//f表示当前的颜色
}T[M*4];
void UP(int p){
    T[p].b=T[p<<1].b+T[p<<1|1].b;
    if(T[p<<1].f==T[p<<1|1].f&&T[p<<1].f)T[p].f=T[p<<1].f;
    else T[p].f=0;
}
void down(int l,int r,int p){
    if(T[p].c==0)return ;
    int mid=(l+r)>>1;
    ll x=T[p].c;
    T[p<<1].b+=1ll*(mid-l+1)*x;//[l,mid];
    T[p<<1|1].b+=1ll*(r-mid)*x;//[mid+1,r]
    T[p<<1|1].f=T[p<<1].f=T[p].f;
    T[p<<1].c+=x;T[p<<1|1].c+=x;
    T[p].c=0;
}
void build(int l,int r,int p){
    T[p].f=0;T[p].c=0;T[p].b=0;
    if(l==r){T[p].f=l;return ;}
    int mid=(l+r)>>1;
    build(l,mid,p<<1);
    build(mid+1,r,p<<1|1);
}
void update(int L,int R,int l,int r,int x,int p){
    if(L==l&&R==r&&T[p].f){//[l,r]内的颜色更新为x 
        T[p].b+=1ll*(r-l+1)*abs(T[p].f-x);//
        T[p].c+=abs(T[p].f-x);//答案要叠加
T[p].f=x;
        return ;
    }
    down(L,R,p);
    int mid=(L+R)>>1;
    if(r<=mid)update(L,mid,l,r,x,p<<1);
    else if(l>mid)update(mid+1,R,l,r,x,p<<1|1);
    else {update(L,mid,l,mid,x,p<<1);update(mid+1,R,mid+1,r,x,p<<1|1);}
    UP(p)//更新完再Up回来
}
ll query(int L,int R,int l,int r,int p){
    down(L,R,p);
    if(L==l&&R==r)return T[p].b;
    int mid=(L+R)>>1;
    if(r<=mid)return query(L,mid,l,r,p<<1);
    else if(l>mid)return query(mid+1,R,l,r,p<<1|1);
    else return query(L,mid,l,mid,p<<1)+query(mid+1,R,mid+1,r,p<<1|1);
}
int main(){
    int i,j,k,a,b,c,d;
    scanf("%d %d",&n,&m);
    build(1,n,1);
    for(i=1;i<=m;i++){
        rd(a);rd(b);rd(c);
        if(a==1){
            rd(d);
            update(1,n,b,c,d,1);
        }
        else sc(query(1,n,b,c,1));  
    }
    return 0;
}</span>
20160627离线赛/CodeForces 444C

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值