Codeforces Round #254 (Div. 1) C - DZY Loves Colors 线段树|lazytag维护区间加

开一个变量维护同一个区间内颜色是否相同,而且显然要用lazytag了

递归到颜色相同的区间时就可以直接打标记

然后对于标记,维护的就是常规区间加的部分

(最开始没写lazy,wa6,没明白自己怎么错的,但是又觉得要加lazy很合理:) 

由于有区间推平的操作,用珂朵莉树也可以,详情见洛谷题解区

复制代码
#include<bits/stdc++.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
struct seg{
    int l,r;
    ll len,col,sum,lazy;
    //
}t[maxn<<2];
void push_up(int rt){
    t[rt].sum=t[ls].sum+t[rs].sum;
    if(t[rs].col==t[ls].col) {
        t[rt].col=t[ls].col;
    }
    else t[rt].col=0;
}
void push_down(int rt){
    if(!t[rt].col) return;
    t[ls].lazy+=t[rt].lazy;//lazy 维护的是 多出来的贡献,至于abs的部分,不在这里维护 
    t[rs].lazy+=t[rt].lazy;
    t[ls].sum+=t[rt].lazy*t[ls].len;
    t[rs].sum+=t[rt].lazy*t[rs].len;
    t[ls].col=t[rs].col=t[rt].col;
    t[rt].lazy=0;
    t[rt].col=0;// 可能短期内col不修改没影响,但是为了形式统一emmm 
}
void build(int rt,int l,int r){
    t[rt].l=l;t[rt].r=r;t[rt].len=1ll*(r-l+1);
    if(l==r){
       t[rt].sum=0;
       t[rt].col=1ll*l;
       t[rt].lazy=0;
       return;
    }
    int mid=(l+r)>>1;
    build(ls,l,mid);build(rs,mid+1,r);
    push_up(rt);
}
void update(int rt,int l,int r,ll val){
    if(l<=t[rt].l&&t[rt].r<=r){
        // update
        if(t[rt].col){
           t[rt].sum+=t[rt].len*abs(val-t[rt].col);
           t[rt].lazy+=abs(val-t[rt].col);
           t[rt].col=val;
           return;    
        }  
    }
    push_down(rt);
    if(t[ls].r>=l) update(ls,l,r,val);
    if(t[rs].l<=r) update(rs,l,r,val);
    push_up(rt);
}
ll query(int rt,int l,int r){
    if(l<=t[rt].l&&t[rt].r<=r){
        return t[rt].sum;//
    }
    push_down(rt);
    ll ans=0;
    if(t[ls].r>=l) ans+=query(ls,l,r);//
    if(t[rs].l<=r) ans+=query(rs,l,r);//
    push_up(rt);
    return ans;
} 
int n,m;
int main(){
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n>>m;
    build(1,1,n);
    for(int i=1;i<=m;i++){
      int op;cin>>op;
      if(op==1){
           int l,r;ll x;cin>>l>>r>>x;
           update(1,l,r,x);
      }    
      else {
           int l,r;cin>>l>>r;
           cout<<query(1,l,r)<<endl;
      }    
     }
}
复制代码

 

posted @   liyishui  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示