开一个变量维护同一个区间内颜色是否相同,而且显然要用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; } } }
标签:rt,int,Codeforces,update,Colors,ls,Loves,区间,lazytag From: https://www.cnblogs.com/liyishui2003/p/17167659.html