DZY Loves Colors
题意:n个点,1~n标号,开始时,每个点的颜色标号等于本身编号,每个点的colorfulness值为0;如果将i点的颜色由x改为y,则i点的colorfulness值增加abs(x-y);现有两种操作:1 l r x:表示将区间[l, r]的点全部涂改为x颜色;2 l r:表示求区间[l, r]的colorfulness值之和;
思路:很明显是个区间更新的线段树,怎么如果x节点的子区间颜色不同,那么就必须更新到子区间,如果染色相同,可以先标记,在用到子区间时再更新;所以tr[m].col=tr[m<<1].col==tr[m<<1].col?tr[m<<1].col:0;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
struct node{
int l, r, col;//l, r是该节点的区间范围; col表示该区间的颜色,如果区间颜色相同就是区间颜色的编号,若不同记为0;
ll lazy, sum;//lazy表示该区间的colorfulness值的变化, sum表示区间的colorfulness值之和;
}tr[maxn<<2];
void pushup(int m){
tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
tr[m].col=tr[m<<1].col==tr[m<<1|1].col?tr[m<<1].col:0;//区间的颜色不同是记为0;
}
void pushdown(int m){
if(tr[m].col)//如果区间的颜色相同就可以进行区间更新;
{
tr[m<<1].col=tr[m<<1|1].col=tr[m].col;//更新孩子的col值;
tr[m<<1].sum+=tr[m].lazy*(ll)(tr[m<<1].r-tr[m<<1].l+1);//更新孩子的sum值;
tr[m<<1|1].sum+=tr[m].lazy*(ll)(tr[m<<1|1].r-tr[m<<1|1].l+1);
tr[m<<1].lazy+=tr[m].lazy;//更新孩子的lazy值;
tr[m<<1|1].lazy+=tr[m].lazy;
tr[m].lazy=0;//本lazy已更新,归零;
}
}
void build(int m, int l, int r){
tr[m].l=l;
tr[m].r=r;
tr[m].lazy=0;
if(l==r){
tr[m].col=l;
tr[m].sum=0;
return;
}
int mid=(l+r)>>1;
build(m<<1, l, mid);
build(m<<1|1, mid+1, r);
pushup(m);
}
void updata(int m, int l, int r, int val){
if(tr[m].col&&tr[m].l==l&&tr[m].r==r){
tr[m].sum+=(ll)(tr[m].r-tr[m].l+1)*(ll)abs(val-tr[m].col);
tr[m].lazy+=(ll)abs(val-tr[m].col);
tr[m].col=val;
return;
}
pushdown(m);
int mid=(tr[m].l+tr[m].r)>>1;
if(r<=mid) updata(m<<1, l, r, val);
else if(l>mid) updata(m<<1|1, l, r, val);
else{
updata(m<<1, l, mid, val);
updata(m<<1|1, mid+1, r, val);
}
pushup(m);
}
ll query(int m, int l, int r){
if(tr[m].l==l&&tr[m].r==r){
return tr[m].sum;
}
pushdown(m);
int mid=(tr[m].l+tr[m].r)>>1;
ll temp;
if(r<=mid) temp=query(m<<1, l, r);
else if(l>mid) temp=query(m<<1|1, l, r);
else{
temp=query(m<<1, l, mid)+query(m<<1|1, mid+1, r);
}
pushup(m);
return temp;
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
build(1, 1, n);
while(m--){
int type;
scanf("%d", &type);
if(type==1){
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
updata(1, l, r, x);
}
else{
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", query(1, l, r));
}
}
return 0;
}