版权声明:本文为博主原创文章,未经博主允许也可以转载。 https://blog.csdn.net/FrankAx/article/details/81980026
题目链接
题意:2个操作:
1:l,r,x,数组1区间l-r全部由y(初始为对应位置 i )变为x,此时数组2每个位置加上|x-y|。
2: l , r 询问数组2 的 l - r 的和。
思路:可以把数组1和2放到一个线段树维护更新(当然开两个也是可以的),col为数组1,sum为数组2,对于数组1,两个儿子颜色相同才能有颜色。对于数组2,就是求和。
懒惰标记记录每次更新后节点颜色与更新颜色的差值。
需要注意的是中间会爆int
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e5+66;
int tot ;
struct Node{
int col ;
LL sum ;
LL lazy ;
}s[AX<<2];
void pushUp( int rt ){
s[rt].sum = s[rt<<1].sum + s[rt<<1|1].sum ;
if( s[rt<<1].col == s[rt<<1|1].col ){
s[rt].col = s[rt<<1].col;
}else s[rt].col = 0 ;
return ;
}
void pushDown( int rt , int L , int R ){
if( s[rt].col && s[rt].lazy ){
int mid = ( L + R ) >> 1 ;
s[rt<<1].col = s[rt].col ;
s[rt<<1|1].col = s[rt].col ;
s[rt<<1].sum += ( mid - L + 1 ) * s[rt].lazy ;
s[rt<<1|1].sum += ( R - mid ) * s[rt].lazy ;
s[rt<<1].lazy += s[rt].lazy;
s[rt<<1|1].lazy += s[rt].lazy;
s[rt].lazy = 0 ;
}
return ;
}
void build( int l , int r , int rt ){
if( l == r ){
s[rt].col = ++tot;
return ;
}
int mid = ( l + r ) >> 1 ;
build( l , mid , rt << 1 );
build( mid + 1 , r , rt << 1 | 1 );
pushUp(rt);
}
void update( int L , int R , int v , int l , int r , int rt ){
if( L <= l && R >= r && s[rt].col ){
s[rt].sum += (LL)((LL)( r - l + 1 ) * (LL)abs( v - s[rt].col ));
s[rt].lazy += abs( v - s[rt].col );
s[rt].col = v;
return;
}
pushDown( rt , l , r );
int mid = ( l + r ) >> 1 ;
if( L <= mid ) update( L , R , v , l , mid , rt << 1 );
if( R > mid ) update( L , R , v , mid + 1 , r , rt << 1 | 1 );
pushUp(rt);
}
LL query( int L , int R , int l , int r , int rt ){
if( L <= l && R >= r ){
return s[rt].sum;
}
pushDown( rt , l , r );
LL ans = 0LL ;
int mid = ( l + r ) >> 1 ;
if( L <= mid ) ans += query( L , R , l , mid , rt << 1 );
if( R > mid ) ans += query( L , R , mid + 1 , r , rt << 1 | 1 );
pushUp(rt);
return ans ;
}
int main(){
int n, m ;
int op ;
int l , r , x ;
scanf("%d%d",&n,&m);
tot = 0;
build( 1 , n , 1 );
while( m -- ){
scanf("%d",&op);
if( op == 1 ){
scanf("%d%d%d",&l,&r,&x);
update( l , r , x , 1 , n , 1 );
}else{
scanf("%d%d",&l,&r);
printf("%I64d\n",query( l , r , 1 , n , 1 ) );
}
}
return 0 ;
}