Codeforces444 C. DZY Loves Colors(线段树)

题意:

有n个格子,一开始第i个格子的颜色为i,权值为0。
现在要进行m次操作,操作有两种:
(1,l,r,x)将区间[l,r]的所有格子修改为x颜色,如果一个格子之前的颜色是y,那么权值增加abs(x-y)
(2,l,r)计算区间[l,r]的权值和

数据范围:n,m<=1e5,x<=1e8

解法:

线段树

如果待修改区间的颜色相同,那么就可以整块一起维护,
如果不相同,似乎没办法一起维护,那么递归找相同颜色的子区间。
开一个颜色标记维护区间颜色是否相同以及记录颜色就行了。

颜色覆盖需要开一个颜色laz标记进行颜色下传
因为还需要维护权值,所以还需要一个权值laz标记进行权值下传

区间和是基本的区间和标记

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
int sum[maxm<<2];
int add[maxm<<2];
int col[maxm<<2];
int a[maxm<<2];
int n,m;
void pushup(int node){
    if(a[node*2]&&a[node*2+1]&&a[node*2]==a[node*2+1]){
        a[node]=a[node*2];
    }else{
        a[node]=0;
    }
    sum[node]=sum[node*2]+sum[node*2+1];
}
void pushdown(int node,int l,int r){
    if(col[node]){//颜色修改标记
        a[node*2]=col[node];
        a[node*2+1]=col[node];
        col[node*2]=col[node];
        col[node*2+1]=col[node];
        col[node]=0;
    }
    if(add[node]){//权值累加标记
        int mid=(l+r)/2;
        sum[node*2]+=add[node]*(mid-l+1);
        sum[node*2+1]+=add[node]*(r-mid);
        add[node*2]+=add[node];
        add[node*2+1]+=add[node];
        add[node]=0;
    }
}
void build(int l,int r,int node){
    if(l==r){
        a[node]=l;return ;
    }
    int mid=(l+r)/2;
    build(l,mid,node*2);
    build(mid+1,r,node*2+1);
    pushup(node);
}
void update(int st,int ed,int val,int l,int r,int node){
    if(st<=l&&ed>=r&&a[node]){
        sum[node]+=abs(val-a[node])*(r-l+1);
        add[node]+=abs(val-a[node]);//权值下传只需要下传差值就行了
        a[node]=val;
        col[node]=val;
        return ;
    }
    pushdown(node,l,r);
    int mid=(l+r)/2;
    if(st<=mid)update(st,ed,val,l,mid,node*2);
    if(ed>mid)update(st,ed,val,mid+1,r,node*2+1);
    pushup(node);
}
int ask(int st,int ed,int l,int r,int node){
    if(st<=l&&ed>=r)return sum[node];
    pushdown(node,l,r);
    int mid=(l+r)/2;
    int ans=0;
    if(st<=mid)ans+=ask(st,ed,l,mid,node*2);
    if(ed>mid)ans+=ask(st,ed,mid+1,r,node*2+1);
    return ans;
}
signed main(){
    cin>>n>>m;
    build(1,n,1);
    while(m--){
        int op;cin>>op;
        if(op==1){
            int l,r,x;cin>>l>>r>>x;
            update(l,r,x,1,n,1);
        }else{
            int l,r;cin>>l>>r;
            int ans=ask(l,r,1,n,1);
            cout<<ans<<endl;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/107455203