题意:线段树的题,两个操作(原始每个节点值都是i,每个节点的cnt都是0)
1.把一段都涂成x,每个点的cnt加上abs( 原来的值-更改后的值 )
2.查询一段cnt的和
不错的线段树,有地方需要优化
lazy 、 sum 双重延时标记
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define lson l, mid, x<<1
#define rson mid+1, r, x<<1|1
using namespace std;
const int maxn=300005;
typedef __int64 ll;
struct node
{
int ma;
int mi;
ll sum;//区间内的每个点都改变这样一个值
ll sum1;//区间的那个和
ll lazy;//区间上每个点的值(染色那个)
ll l, r;
}tree[maxn*4];
void pushup( int x )
{
ll q1 = tree[x<<1].r-tree[x<<1].l+1;
ll q2 = tree[x<<1|1].r-tree[x<<1|1].l+1;
tree[x].sum1 = tree[x<<1].sum1+tree[x<<1|1].sum1+tree[x<<1].sum*q1+tree[x<<1|1].sum*q2;;
}
void pushdown( int x )
{
if( tree[x].lazy ){
tree[x<<1].lazy = tree[x<<1|1].lazy = tree[x].lazy;
tree[x].lazy = 0;
}
}
void build( int l, int r, int x )
{
tree[x].l = l;tree[x].r = r;tree[x].lazy = 0;
if( l == r ){
tree[x].sum = tree[x].sum1 = 0;
tree[x].lazy = l;
return;
}
int mid = (l+r)>>1;
build( lson );
build( rson );
pushup(x);
}
void update( int L, int R, ll val, int l, int r, int x )
{
// 在对区间做任何修改之前,先pushdown
int mid = (l+r) >> 1;
if( L == l && R == r ){
if( tree[x].lazy ){
tree[x].sum += abs( val - tree[x].lazy );
//tree[x].sum1 += (ll)( r-l+1 )*abs( val - tree[x].lazy );
tree[x].lazy = val;
return ;// 优化之后这里会有问题,如果只修改sum1的话,下次需要修改区间内部的sum1就没办法修改了,而如果既修改sum和sum1,分不清sum中哪一部分是这次修改的,哪一部分是之前修改的,所以还不如一起算
}
else{
//pushdown(x); // 没有标记不用下放
update( L, mid, val, lson );
update( mid+1, R, val, rson );
pushup(x);
tree[x].lazy = val;// 这里就是优化! 把它区间修改后,因为已经是同一段数了,要把它变成同一段数,修改lazy
return ;
}
}
pushdown(x);
if( R <= mid ) update( L, R, val, lson );
else if( L > mid ) update( L, R, val, rson );
else{
update( L, mid, val, lson );
update( mid+1, R, val, rson );
}
pushup(x);
}
ll query( int L, int R, int l, int r, int x )
{
if( l == L && R == r ){
//if( tree[x].sum ){
// tree[x].sum1 += ( r-l+1 )*tree[x].sum;
// tree[x].sum = 0;
return tree[x].sum1+(ll)(r-l+1)*tree[x].sum;
//}
}
int mid = ( l + r ) >> 1;
ll res = 0;
if( tree[x].sum ){
tree[x<<1].sum += tree[x].sum;
tree[x<<1|1].sum += tree[x].sum;
tree[x].sum = 0;
}
if( R <= mid ) res += query( L, R, lson );
else if( L > mid ) res += query( L, R, rson );
else{
res += query( L, mid, lson ) + query( mid+1, R, rson );
}
pushup(x);// 任何时候下放标记了以后都需要pushup!!
return res;
// res += (ll)tree[x].sum*( R-L+1 ); // 也可以像宦老板一样不下放标记,直接计算该段的sum
// if( R <= mid ) res += query( L, R, lson );
// else if( L > mid ) res += query( L, R, rson );
// else{
// res += query( L, mid, lson ) + query( mid+1, R, rson );
// }
// return res;
}
int main()
{
int n, m, i, j, x, y;
ll id;
cin >> n >> m;
build( 1, n, 1 );
while( m -- ){
scanf("%I64d", &id);
if( id == 1 ){
scanf("%d %d %I64d", &x, &y, &id);
update( x, y, id, 1, n, 1 );
}
else{
scanf("%d %d", &x, &y);
printf("%I64d\n", query( x, y, 1, n, 1 ));
}
}
}