HDOJ 4107 Gangster 线段树 成段更新变化

本文介绍了一道HDOJ4107 Gangster问题的解决方案,通过线段树实现成段更新操作,具体包括在一定条件下对区间内元素进行加c或2c的操作,并提供了完整的C语言代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//HDOJ 4107 Gangster 线段树 成段更新变化
/*
题意:n个数,初始都是0,m次更新操作:
	  若元素a[i] < p,则a[i]+=c,否则a[i]+=2*c
	  最后输出所有的数字

思路:当一个区间内的最大值mmax<p,则该区间内所有的数都+c,朴素的成段更新
	  当一个区间内的最小是mmax>=p,则该区间内的所有的数都+2*才,朴素的成段更新
	  不满足的话往下一直更新,满足的话lazy后返回
*/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define N 200005
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r

#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)

int mmax[N<<2],mmin[N<<2],add[N<<2];
int n,m,p;

void Pushup(int rt){
	mmax[rt] = Max(mmax[rt<<1],mmax[rt<<1|1]);
	mmin[rt] = Min(mmin[rt<<1],mmin[rt<<1|1]);
}

void Pushdown(int rt){
	if(add[rt]){
		add[rt<<1] += add[rt];
		add[rt<<1|1] += add[rt];
		mmax[rt<<1] += add[rt];
		mmax[rt<<1|1] += add[rt];
		mmin[rt<<1] += add[rt];
		mmin[rt<<1|1] +=add[rt];
		add[rt] = 0;
	}
}

void Build(){
	memset(mmax,0,sizeof(mmax));
	memset(mmin,0,sizeof(mmin));
	memset(add,0,sizeof(add));
}

void Update(int rt,int l,int r,int L,int R,int c){
	if(L <= l && R >= r){
		if(mmax[rt] < p){
			add[rt] += c;
			mmax[rt] += c;
			mmin[rt] += c;
			return;
		}
		if(mmin[rt] >= p){
			add[rt] += 2*c;
			mmax[rt] += 2*c;
			mmin[rt] += 2*c;
			return;
		}
	}
	Pushdown(rt);
	int mid = (l + r) >> 1;
	if(L <= mid) Update(lson,L,R,c);
	if(R > mid ) Update(rson,L,R,c);
	Pushup(rt);
}

void Print(int rt,int l,int r){
	if(l == r){
		if(l == 1)	printf("%d",mmax[rt]);
		else	printf(" %d",mmax[rt]);
		return ;
	}
	Pushdown(rt);
	int mid =(l + r) >> 1;
	Print(lson);
	Print(rson);
}

inline void scan_d(int &ret) {  
    char c; ret=0;  
    while((c=getchar())<'0'||c>'9');  
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();  
}  

int main(){
	int a,b,c;
	while(scanf("%d %d %d",&n,&m,&p)!=EOF){
		Build();
		while(m--){
			scan_d(a);
			scan_d(b);
			scan_d(c);
			Update(1,1,n,a,b,c);
		}
		Print(1,1,n);
		puts("");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值