链接:
http://codeforces.com/contest/444/problem/C
题意:
给你n
个元素,第i
个元素最初的颜色是i
,最初每个元素的权值为0
,有两种操作,第一种操作是区间赋值x
,如果之前元素的颜色为y
,那么赋值之后他的权值增加abs(x-y)
,第二种操作是查询所有元素的权值和。
做法:
首先可以想象如果每次操作区间很大,那么所有元素趋向颜色相同,如果操作区间很小,则可以暴力更新,那么我们可以维护区间颜色是否相同,如果相同则用lazy
进行更新,否则再去子区间进行更新,这里要注意lazy
对于子区间的更新每次都有一个权值的增加,这个也要用一个lazy
数组维护一下。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
struct T
{
int l,r,mid;int col,add;ll sum,inc;
}tree[maxn<<2];
int col[maxn];
void up(int rt)
{
if(tree[rt<<1].col==tree[rt<<1|1].col) tree[rt].col=tree[rt<<1].col;else tree[rt].col=0;tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}
int maxx=0;
void down(int rt)
{
if(tree[rt].add!=0){
int tmp=tree[rt].add;tree[rt<<1].col=tmp;tree[rt<<1].add=tmp;tree[rt<<1|1].col=tmp;tree[rt<<1|1].add=tmp;tree[rt].add=0;}if(tree[rt].inc!=0){
ll tmp=tree[rt].inc;tree[rt<<1].sum+=1LL*tmp*(tree[rt<<1].r-tree[rt<<1].l+1);tree[rt<<1].inc+=tmp;tree[rt<<1|1].sum+=1LL*tmp*(tree[rt<<1|1].r-tree[rt<<1|1].l+1);tree[rt<<1|1].inc+=tmp;tree[rt].inc=0;}}
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;tree[rt].add=0;tree[rt].inc=0;if(l==r){
tree[rt].col=col[l];tree[rt].sum=0;return ;}int mid=tree[rt].mid=l+r>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);up(rt);return ;
}
void update(int rt,int l,int r,int co)
{
if(tree[rt].l>r||tree[rt].r<l) return ;if(tree[rt].l>=l&&tree[rt].r<=r&&tree[rt].col!=0){
tree[rt].sum=tree[rt].sum+1LL*abs(co-tree[rt].col)*(tree[rt].r-tree[rt].l+1);tree[rt].inc+=abs(co-tree[rt].col);tree[rt].col=co;tree[rt].add=co;return ;}down(rt);if(tree[rt].mid>=l) update(rt<<1,l,r,co);if(tree[rt].mid<r) update(rt<<1|1,l,r,co);up(rt);
}
ll query(int rt,int l,int r)
{
if(tree[rt].l>r||tree[rt].r<l) return 0;if(tree[rt].l>=l&&tree[rt].r<=r) return tree[rt].sum;down(rt);ll ans=0;if(tree[rt].mid>=l) ans=ans+query(rt<<1,l,r);if(tree[rt].mid<r) ans=ans+query(rt<<1|1,l,r);return ans;
}
int main()
{
int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) col[i]=i;build(1,1,n);int cnt=0;while(m--){
int op,x,y,z;scanf("%d",&op);if(op==1){
scanf("%d%d%d",&x,&y,&z);update(1,x,y,z);}else{
scanf("%d%d",&x,&y);printf("%lld\n",query(1,x,y));}}return 0;
}