CF444C DZY Loves Colors
DZY喜欢色彩,他热爱绘画。
在一个多姿多彩的日子里,DZY得到了一个彩色的缎带,它由N个单元组成(从左到右从1到n编号)。色带的第ii个单位的最初颜色是i。虽然颜色足够丰富,但我们仍然认为每个单元的颜色数量最初是0。
DZY热衷于绘画,我们知道。他拿起一把彩色X笔,用它在缎带上画一条线。在这种情况下,他就绘制了一段连续的单元。想象一下,单位i被涂之前颜色是Y。被涂之后时,单元的颜色变为X,令单位的颜色增加了∣X−Y∣。 DZY想要执行M个操作,每个操作可以是下列操作之一:
1、将区间[L,R]内单元绘制为颜色X。
2、询问[L,R]之间的单位颜色的总和(包括两者)。
我们用线段树维护这一段的答案和这段颜色是否一样,如果一样是什么颜色
每次我们修改时候对相同的颜色段修改,不相同的颜色段递归暴力修改
对于一次区间覆盖,只会产生两个新的端点,所以只会暴力\(O(n+2m)\)次
复杂度\(O(mlogn)\)
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100000
#define zrt k << 1
#define yrt k << 1 | 1
using namespace std;
int n,m;
struct node
{
int tag,c;
long long su,at;
node ()
{
at = su = c = tag = 0;
}
};
int myabs(int x)
{
if (x > 0)
return x;
return -x;
}
struct Seg
{
node s[N * 4 + 5];
node upd(node x,node y)
{
node k;
if (x.c == y.c)
k.c = x.c;
k.su = x.su + y.su;
return k;
}
void build(int k,int l,int r)
{
if (l == r)
{
s[k].c = l;
s[k].su = 0LL;
return;
}
int mid = l + r >> 1;
build(zrt,l,mid);
build(yrt,mid + 1,r);
s[k] = upd(s[zrt],s[yrt]);
}
void pushdown(int k,int l,int r,int mid)
{
if (!s[k].tag && !s[k].at)
return;
if (s[k].tag)
{
s[zrt].c = s[k].tag;
s[yrt].c = s[k].tag;
s[zrt].tag = s[k].tag;
s[yrt].tag = s[k].tag;
}
if (s[k].at)
{
s[zrt].su += (long long)(mid - l + 1) * s[k].at;
s[yrt].su += (long long)(r - mid) * s[k].at;
s[zrt].su += s[k].at;
s[yrt].su += s[k].at;
}
s[k].tag = s[k].at = 0;
}
void change(int k,int l,int r,int x,int y,int z)
{
if (l >= x && r <= y && s[k].c)
{
s[k].su += (long long)myabs(z - s[k].c) * (long long)(r - l + 1);
s[k].c = z;
s[k].tag = z;
s[k].at += (long long)myabs(z - s[k].c);
return;
}
int mid = l + r >> 1;
pushdown(k,l,r,mid);
if (x > mid)
change(yrt,mid + 1,r,x,y,z);
else
if (y <= mid)
change(zrt,l,mid,x,y,z);
else
change(zrt,l,mid,x,y,z),change(yrt,mid + 1,r,x,y,z);
s[k] = upd(s[zrt],s[yrt]);
}
node query(int k,int l,int r,int x,int y)
{
if (l >= x && r <= y)
return s[k];
int mid = l + r >> 1;
pushdown(k,l,r,mid);
if (x > mid)
return query(yrt,mid + 1,r,x,y);
else
if (y <= mid)
return query(zrt,l,mid,x,y);
else
return upd(query(zrt,l,mid,x,y),query(yrt,mid + 1,r,x,y));
}
}tree;
int main()
{
scanf("%d%d",&n,&m);
tree.build(1,1,n);
int opt,l,r,z;
for (int i = 1;i <= m;i++)
{
scanf("%d%d%d",&opt,&l,&r);
if (opt == 1)
{
scanf("%d",&z);
tree.change(1,1,n,l,r,z);
}
else
printf("%lld\n",tree.query(1,1,n,l,r).su);
}
return 0;
}