【CodeForces】444C DZY Loves Colors 线段树

C. DZY Loves Colors
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

DZY loves colors, and he enjoys painting.

On a colorful day, DZY gets a colorful ribbon, which consists ofn units (they are numbered from 1 to n from left to right). The color of thei-th unit of the ribbon is i at first. It is colorful enough, but we still consider that the colorfulness of each unit is0 at first.

DZY loves painting, we know. He takes up a paintbrush with colorx and uses it to draw a line on the ribbon. In such a case some contiguous units are painted. Imagine that the color of uniti currently is y. When it is painted by this paintbrush, the color of the unit becomesx, and the colorfulness of the unit increases by|x - y|.

DZY wants to perform m operations, each operation can be one of the following:

  1. Paint all the units with numbers between l and r (both inclusive) with colorx.
  2. Ask the sum of colorfulness of the units betweenl and r (both inclusive).

Can you help DZY?

Input

The first line contains two space-separated integersn, m (1 ≤ n, m ≤ 105).

Each of the next m lines begins with a integertype (1 ≤ type ≤ 2), which represents the type of this operation.

If type = 1, there will be3 more integers l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 108) in this line, describing an operation1.

If type = 2, there will be2 more integers l, r (1 ≤ l ≤ r ≤ n) in this line, describing an operation2.

Output

For each operation 2, print a line containing the answer — sum of colorfulness.

Sample test(s)
Input
3 3
1 1 2 4
1 2 3 5
2 1 3
Output
8
Input
3 4
1 1 3 4
2 1 1
2 2 2
2 3 3
Output
3
2
1
Input
10 6
1 1 5 3
1 2 7 9
1 10 10 11
1 3 8 12
1 1 10 3
2 1 10
Output
129
Note

In the first sample, the color of each unit is initially[1, 2, 3], and the colorfulness is [0, 0, 0].

After the first operation, colors become [4, 4, 3], colorfulness become [3, 2, 0].

After the second operation, colors become [4, 5, 5], colorfulness become [3, 3, 2].

So the answer to the only operation of type 2 is 8.


传送门:【CodeForces】444C DZY Loves Colors


题目大意:给你一条长度为n的线段,从左到右分别编号1~n。一开始线段上的颜色就是他的编号,初始所有线段的增量为0。

现在给你m次操作,操作分两种:

1.L R x 将区间[L,R]上的颜色变成x并且每个编号为 i 的单元的增量加上abs(x - i)。

2.L R 查询区间[L,R]上所有单元的增量之和。

(1 ≤ n, m ≤ 105), (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 108)


题目分析:

不知道本题我的方法是否会退化,反正先给一份我的方法吧。

设立两个lazy标记,一个set[ o ]表示当前区间范围为o的区间内的颜色,如果区间内为纯色则set[ o ]的值等于颜色值,否则set[ o ] = 0;一个add[ o ]标记,表示应该向下传递的单位增量。

再设立sum[ o ]表示区间内的增量和。

建树的时候叶子结点的set[ o ] = 自己的编号,其他所有的都为0。

对于线段树的每次更新操作L R x,当到达子区间[ l , r ]时,如果子区间的set[ o ]不为0,则表示该区间为纯色,则可以直接sum[ o ] += abs ( x - set[ o ] ) * ( r - l + 1 ),add[ o ] += abs ( x - set[ o ] ),set[ o ] = x,因为所有的元素都是相同的,增加的增量所以增加的增量可以向下传递。如果到达的子区间[ l , r ]时,子区间的set[ o ] = 0,说明子区间内至少有两种不同的颜色,那么增加的增量就会不一样,无法传递,所以此时只能继续更新下去知道遇到的子区间的set[ o ]不为0。

向上更新父亲的时候注意一下,如果父节点的两个子节点的set值相等,则父节点的set值就等于子节点的set值,目的是为了下次更新时如果遇到父节点就可以直接返回了,不用再多走几步路到子节点。

其他和基本的线段树没什么两样。


PS:感觉还会有数据能卡掉我的代码,希望路过的大神能好心给个证明告诉我是否能够卡掉我的代码。万分感谢!


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define ls ( o << 1 )
#define rs ( o << 1 | 1 )
#define lson ls , l , m
#define rson rs , m + 1 , r
#define rt o , l , r
#define root 1 , 1 , n
#define mid ( ( l + r ) >> 1 )
#define clear( a , x ) memset ( a , x , sizeof a )

typedef long long LL ;

const int MAXN = 100005 ;

int set[MAXN << 2] ;
LL sum[MAXN << 2] ;
LL add[MAXN << 2] ;

void pushUp ( int o , int l , int r ) {
	set[o] = ( set[ls] == set[rs] ? set[ls] : 0 ) ;
	sum[o] = sum[ls] + sum[rs] ;
}

void pushDown ( int o , int l , int r ) {
	int m = mid ;
	if ( set[o] ) set[ls] = set[rs] = set[o] ;
	if ( add[o] ) {
		sum[ls] += add[o] * ( m - l + 1 ) ;
		add[ls] += add[o] ;
		sum[rs] += add[o] * ( r - m ) ;
		add[rs] += add[o] ;
		add[o] = 0 ;
	}
}

void build ( int o , int l , int r ) {
	add[o] = set[o] = sum[o] = 0 ;
	if ( l == r ) {
		set[o] = l ;
		return ;
	}
	int m = mid ;
	build ( lson ) ;
	build ( rson ) ;
}

void update ( int x , int L , int R , int o , int l , int r ) {
	if ( L <= l && r <= R ) {
		if ( set[o] ) {
			add[o] += abs ( x - set[o] ) ;
			sum[o] += ( LL ) abs ( x - set[o] ) * ( r - l + 1 ) ;
			set[o] = x ;
			return ;
		}
	}
	pushDown ( rt ) ;
	int m = mid ;
	if ( L <= m ) update ( x , L , R , lson ) ;
	if ( m <  R ) update ( x , L , R , rson ) ;
	pushUp ( rt ) ;
}

LL query ( int L , int R , int o , int l , int r ) {
	if ( L <= l && r <= R ) return sum[o] ;
	pushDown ( rt ) ;
	int m = mid ;
	LL ans = 0 ;
	if ( L <= m ) ans += query ( L , R , lson ) ;
	if ( m <  R ) ans += query ( L , R , rson ) ;
	return ans ;
}

void work () {
	int n , m ;
	int type , l , r , x ;
	while ( ~scanf ( "%d%d" , &n , &m ) ) {
		build ( root ) ;
		while ( m -- ) {
			scanf ( "%d%d%d" , &type , &l , &r ) ;
			if ( type == 1 ) {
				scanf ( "%d" , &x ) ;
				update ( x , l , r , root ) ;
			}
			else printf ( "%I64d\n" , query ( l , r , root ) ) ;
		}
	}
}

int main () {
	work () ;
	return 0 ;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值