您的位置:首页 > 其它

Codeforces 444 C. DZY Loves Colors (线段树+剪枝)

2016-09-25 19:43 323 查看
题目链接:http://codeforces.com/contest/444/problem/C

给定一个长度为n的序列,初始时ai=i,vali=0(1≤i≤n).有两种操作:

将区间[L,R]的值改为x,并且当一个数从y改成x时它的权值vali会增加|x−y|.

询问区间[L,R]的权值和.

n≤10^5,1≤x≤10^6.

感觉这是一个比较好的考察线段树区间更新的性质。

当区间的a[i]一样时,区间更新即可,这是剪枝。

注意,lazy标记存的是增量。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
struct SegTree {
LL l, r, Min, Max;
LL val, lazy;
}T[N << 2];

LL Abs(LL a) {
return a < 0 ? -a : a;
}

void pushup(int p) {
T[p].Min = min(T[p << 1].Min, T[(p << 1)|1].Min);
T[p].Max = max(T[p << 1].Max, T[(p << 1)|1].Max);
T[p].val = T[p << 1].val + T[(p << 1)|1].val;
}

void pushdown(int p) {
if(T[p].l == T[p].r) {
return ;
} else if(T[p].lazy) {
T[p << 1].lazy += T[p].lazy;
T[(p << 1)|1].lazy += T[p].lazy;
T[p << 1].val += T[p].lazy*(LL)(T[p << 1].r - T[p << 1].l + 1);
T[(p << 1)|1].val += T[p].lazy*(LL)(T[(p << 1)|1].r - T[(p << 1)|1].l + 1);
T[p << 1].Min = T[p << 1].Max = T[(p << 1)|1].Max = T[(p << 1)|1].Min = T[p].Min;
T[p].lazy = 0;
}
}

void build(int p, int l, int r) {
int mid = (l + r) >> 1;
T[p].l = l, T[p].r = r, T[p].lazy = 0;
if(l == r) {
T[p].Max = l, T[p].Min = l;
T[p].val = 0;
return ;
}
build(p << 1, l, mid);
build((p << 1)|1, mid + 1, r);
pushup(p);
}

void update(int p, int l, int r, LL add) {
int mid = (T[p].l + T[p].r) >> 1;
pushdown(p);
if(l == T[p].l && T[p].r == r && T[p].Min == T[p].Max) {
T[p].val += (LL)Abs(add - T[p].Min)*(LL)(r - l + 1);
T[p].lazy += Abs(add - T[p].Max);
T[p].Max = T[p].Min = add;
return ;
}
if(r <= mid) {
update(p << 1, l, r, add);
} else if(l > mid) {
update((p << 1)|1, l, r, add);
} else {
update(p << 1, l, mid, add);
update((p << 1)|1, mid + 1, r, add);
}
pushup(p);
}

LL query(int p, int l, int r) {
int mid = (T[p].l + T[p].r) >> 1;
pushdown(p);
if(l == T[p].l && T[p].r == r) {
return T[p].val;
}
if(r <= mid) {
return query(p << 1, l, r);
} else if(l > mid) {
return query((p << 1)|1, l, r);
} else {
return query(p << 1, l, mid) + query((p << 1)|1, mid + 1, r);
}
pushup(p);
}

int main()
{
int n, m, l, r, c;
LL add;
scanf("%d %d", &n, &m);
build(1, 1, n);
while(m--) {
scanf("%d %d %d", &c, &l, &r);
if(c == 1) {
scanf("%lld", &add);
update(1, l, r, add);
} else {
printf("%lld\n", query(1, l, r));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: