Codeforces 444C DZY Loves Colors(线段树+绝对值)

题目链接

之前遇到线段树+取模的组合,相比那题,这题比较友好,但也难度中等,记录一下。

/*  
题目大意:
    有长度为n的数组,起始值A[i] = i,sum[i] = 0现给两种操作
  	1 left right x: 
    将A[left],A[left + 1].....A[right]都改为x,sum[i] = abs(x - A[i]);
  	2 left right
  	统计[left,right]的sum之和
  	----------------------
  	一个有初值的长度n的数组,每次区间修改成同一个值,要记录其中数值的变化大小 
  	每次区间查询当前区间之前变化大小的总和。 
  	----------------------
  	线段树与绝对值的组合
	---------------------- 
	n,m-1e5  ---开4倍 
	修改的值-1e8 ---用ll 
	----------------------

解析:
	一个个单个修改绝对T,区间修改遇到 这个区间数组值不同 时,绝对值有误差
	-->加个判断数组f[maxn<<2],判断这个区间是否都是同一值 
*/
#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+7;
const int mod=1e9+7;
int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+ch-'0';
        ch=getchar();
    }
    return x*f;
}
#define ls i<<1
#define rs i<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
int n,m,x,y,z;
struct node{
	int l,r,len;
	ll a,sum,lazy;
	bool f;
}t[maxn<<2];
//a[]这个区间的数组数,sum[]这个区间的代价值
//lazy延迟标记,f[]判断这个区间是否为同一数
void pushup(int i){
	t[i].sum=t[ls].sum+t[rs].sum;
	if(t[ls].f&&t[rs].f&&t[ls].a==t[rs].a){
		t[i].f=1;
		t[i].a=t[ls].a;
	}
	else	t[i].f=0;
}
//c为修改后的数组值,add为之前的值与c的差的绝对值
void change(int i,ll c,ll add){
	t[i].sum+=(ll)t[i].len*add;
	t[i].lazy+=add;
	t[i].a=c;
}
void pushdown(int i){
	if(t[i].lazy){
		ll temp=t[i].lazy;
		change(ls,t[i].a,temp);
		change(rs,t[i].a,temp);
		t[i].lazy=0;
	}
}
void build(int i,int l,int r) {
	t[i].l=l;	t[i].r=r;	t[i].len=r-l+1;
	t[i].sum=t[i].lazy=t[i].a=t[i].f=0;		//可省略
	if(l==r){
		t[i].f=1;	t[i].a=l;
		return;
	}
	int mid=l+r>>1;
	build(lson);	build(rson);
	pushup(i);
}
void update(int i,int l,int r,ll c){
	if(t[i].l>r||t[i].r<l)	return;
	if(l<=t[i].l&&t[i].r<=r&&t[i].f){
		change(i,c,abs(t[i].a-c));
		return;
	}
	pushdown(i);
	update(ls,l,r,c);	update(rs,l,r,c);
	pushup(i);
}
ll query(int i,int l,int r){
	if(t[i].l>r||t[i].r<l)	return 0;
	if(l<=t[i].l&&t[i].r<=r)	return t[i].sum;
	pushdown(i);
	return query(ls,l,r)+query(rs,l,r);
}
int main(){
	n=read();	m=read();
	build(1,1,n);
	while(m--){
		x=read();
		if(x==1){
			x=read();	y=read();	z=read();
			update(1,x,y,z);
		}
		else{
			x=read();	y=read();
			printf("%lld\n",query(1,x,y));
		}
	}
}

/*
样例一
3 3
1 1 2 4
1 2 3 5
2 1 3

8
样例二
3 4
1 1 3 4
2 1 1
2 2 2
2 3 3

3
2
1
样例三
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

129

*/
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值