【线段树】 codeforces 444C DZY Loves Colors

考虑一段区间如果颜色相同就可以合并。记录三个变量,颜色,增量,总和。颜色为正数时表示该段区间全为改颜色,为0时表示该段区间至少有一个颜色不同。。。更新时一定要更新到颜色不为0的节点,否则就向下更新。。。

#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#define maxn 100005
#define eps 1e-6
#define mod 20090717
#define INF 99999999
#define lowbit(x) (x&(-x))
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;

LL color[maxn<<2];
LL sum[maxn<<2];
LL delta[maxn<<2];
int n, m, ql, qr, x;
LL ans;

void build(int o, int L, int R)
{
	if(L==R) {
		sum[o] = delta[o] = 0;
		color[o] = L;
		return;
	}
	color[o] = 0;
	int mid = (L+R)>>1;
	build(lson);
	build(rson);
}
void pushup(int o, int L, int R)
{
	if(color[o<<1] == color[o<<1 | 1])
		color[o] = color[o<<1];
	else color[o] = 0;
	sum[o] = sum[o<<1] + sum[o<<1 | 1];
}
void pushdown(int o, int L, int R)
{
	if(!color[o]) return;
	int mid = (R+L)>>1;
	delta[o<<1] += delta[o];
	delta[o<<1 | 1] += delta[o];
	sum[o<<1] += delta[o]*(mid - L + 1);
	sum[o<<1 | 1] += delta[o]*(R - mid);
	color[o<<1] = color[o<<1 | 1] = color[o];
	delta[o] = color[o] = 0;
}
void updata(int o, int L, int R)
{
	if(ql <= L && qr >= R && color[o]) {
		delta[o] += abs(color[o] - x);
		sum[o] += abs(color[o] - x)*(R-L+1);
		color[o] = x;
		return;
	}
	pushdown(o, L, R);
	int mid = (L+R)>>1;
	if(ql<=mid) updata(lson);
	if(qr>mid) updata(rson);
	pushup(o, L, R);
}
void query(int o, int L, int R)
{
	if(ql <= L && qr >= R){
		ans += sum[o];
		return;
	}
	pushdown(o, L, R);
	int mid = (L+R)>>1;
	if(ql<=mid) query(lson);
	if(qr>mid) query(rson);
	pushup(o, L, R);
}
void debug(void)
{
	printf("%I64d %I64d\n", sum[4], sum[5]);
}
void solve(void)
{
	int k;
	while(m--) {
		scanf("%d", &k);
		if(k == 1) {
			scanf("%d%d%d", &ql, &qr, &x);
			updata(1, 1, n);
		}
		else {
			scanf("%d%d", &ql, &qr);
			ans = 0;
			query(1, 1, n);
			printf("%I64d\n", ans);
		}
	}
}
int main(void)
{
	scanf("%d%d", &n, &m);
	build(1, 1, n);
	solve();
	return 0;
}



你可能感兴趣的:(线段树)