hdu 4578 Transformation (线段树 + 延迟标记)

本文介绍了解决HDU4578问题的方法,该问题涉及区间更新和查询,通过使用线段树和懒惰传播实现高效操作。文章详细解释了三种操作的优先级及其如何影响线段树节点的状态更新。

题目链接:hdu 4578

思路:这道题目有个关键点,就是三个操作的优先级,优先级如下:1改变>2乘>3加,可以这么理解,先定义三个lazy0,lazy1,lazy2的意义,分别表示将要加的数,将要乘上的数,将要变成的数c,那么一旦你执行操作1(改变),那么lazy2=c, lazy1要置为1,lazy0要置于0,同样,你一旦操作2乘c,那么你lazy1=lazy1*c,lazy0=lazy0*c。 最后,你如果操作3加,那么你只要将lazy0=lazy0 + c. 所以可以看出优先级是改变>乘>加。 因此pushdown的时候,因先对优先级高的先操作,因为它会影响后面的操作。

代码:

#include<cstdio>
#define ll long long 
const int mod = 10007;
const int maxn = 1e5+5;
#define mid (L + R)/2
#define ls rt*2
#define rs rt*2+1
#define lson ls,L,mid
#define rson rs,mid+1,R
ll sum[maxn<<2], sum1[maxn<<2], sum2[maxn<<2];
ll lazy0[maxn<<2], lazy1[maxn<<2], lazy2[maxn<<2];//加,乘,变 
void build(int rt, int L, int R)
{
	lazy0[rt]=lazy2[rt]=sum[rt]=sum1[rt]=sum2[rt]= 0;
	lazy1[rt] = 1;
	if(L == R) return ;
	build(lson);
	build(rson);
}
void pushDown(int rt, int  L, int R)
{
	if(lazy2[rt]){//变 
		sum2[ls] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(mid-L+1))%mod;
		sum2[rs] = 1ll*(((lazy2[rt]*lazy2[rt])%mod*lazy2[rt])%mod*(R-mid))%mod;
		sum1[ls] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(mid-L+1))%mod;
		sum1[rs] = 1ll*((lazy2[rt]*lazy2[rt])%mod*(R-mid))%mod;
		sum[ls] = 1ll*lazy2[rt]*(mid-L+1)%mod; 
		sum[rs] = 1ll*lazy2[rt]*(R-mid)%mod;
		lazy2[ls] = lazy2[rs] = lazy2[rt];
		lazy1[ls] = lazy1[rs] = 1;
		lazy0[ls] = lazy0[rs] = 0;
		lazy2[rt] = 0;
	}
	if(lazy1[rt] != 1){//乘 
		sum2[ls] = 1ll*((sum2[ls]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
		sum2[rs] = 1ll*((sum2[rs]*lazy1[rt])%mod*(lazy1[rt]*lazy1[rt])%mod)%mod;
		sum1[ls] = 1ll*(sum1[ls]*lazy1[rt])%mod*lazy1[rt]%mod;
		sum1[rs] = 1ll*(sum1[rs]*lazy1[rt])%mod*lazy1[rt]%mod;
		sum[ls] = 1ll*sum[ls]*lazy1[rt]%mod;
		sum[rs] = 1ll*sum[rs]*lazy1[rt]%mod;
		lazy1[ls] = 1ll*lazy1[ls]*lazy1[rt]%mod;
		lazy1[rs] = 1ll*lazy1[rs]*lazy1[rt]%mod;
		if(lazy0[ls])
			lazy0[ls] = 1ll*lazy0[ls]*lazy1[rt]%mod;
		if(lazy0[rs])
			lazy0[rs] = 1ll*lazy0[rs]*lazy1[rt]%mod;
		lazy1[rt] = 1;
	}
	if(lazy0[rt]){//加 sum2[rt] + 1ll*(R-L+1)*val*val*val + 3ll*val*(sum[rt]*val + 1ll*sum1[rt]);
		sum2[ls] = sum2[ls] + 1ll*((mid-L+1)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*(lazy0[rt]*((sum[ls]*lazy0[rt])%mod + 1ll*sum1[ls])%mod)%mod;
		sum2[ls] %= mod;
		sum2[rs] = sum2[rs] + 1ll*((R-mid)*(lazy0[rt]*lazy0[rt])%mod*lazy0[rt])%mod + 3ll*lazy0[rt]*(sum[rs]*lazy0[rt] + 1ll*sum1[rs]);
		sum2[rs] %= mod;
		sum1[ls] = sum1[ls] + 1ll*lazy0[rt]*lazy0[rt]*(mid-L+1) + 2ll*sum[ls]*lazy0[rt];
		sum1[ls] %= mod;
		sum1[rs] = sum1[rs] + 1ll*lazy0[rt]*lazy0[rt]*(R-mid) + 2ll*sum[rs]*lazy0[rt];
		sum1[rs] %= mod;
		sum[ls] = sum[ls] + 1ll*lazy0[rt]*(mid-L+1);
		sum[ls] %= mod;
		sum[rs] = sum[rs] + 1ll*lazy0[rt]*(R-mid);
		sum[rt] %= mod;
		lazy0[ls] += lazy0[rt];
		lazy0[ls] %= mod;
		lazy0[rs] += lazy0[rt];
		lazy0[rs] %= mod; 
		lazy0[rt] = 0;
	}
}
void upDate(int rt, int L, int R, int l, int r, ll val, int op)
{
	if(l <= L && R <= r){//加 
		if(op == 1){
			sum2[rt] = sum2[rt] + 1ll*(R-L+1)*((val*val)%mod*val)%mod + 3ll*val*(((sum[rt]*val)%mod + 1ll*sum1[rt]))%mod;
			sum2[rt] %= mod;
			sum1[rt] = sum1[rt]+1ll*(R-L+1)*(val*val)%mod+2ll*(val*sum[rt])%mod;
			sum1[rt] %= mod;
			sum[rt] = sum[rt] + 1ll*val*(R - L + 1);
			sum[rt] %= mod;			
			lazy0[rt] += val;
			lazy0[rt] %= mod;
		}
		else if(op == 2){//乘 
			sum2[rt] = 1ll*sum2[rt]*((val*val)%mod*val)%mod;
			sum1[rt] = 1ll*(sum1[rt] * (val*val)%mod)%mod;
			sum[rt] = 1ll*val*sum[rt]%mod;
			if(lazy0[rt])
				lazy0[rt] = 1ll*lazy0[rt]*val%mod;
			lazy1[rt] = 1ll*lazy1[rt]*val%mod;
		}
		else if(op == 3){//变 
			sum2[rt] = 1ll*((val*val)%mod*val*(R-L+1))%mod;
			sum1[rt] = 1ll*val*val*(R-L+1)%mod;
			sum[rt] = 1ll*val*(R - L + 1)%mod;
			lazy0[rt] = 0;
			lazy1[rt] = 1;
			lazy2[rt] = val;
		}
		return ;
	}
	pushDown(rt, L, R);
	if(l <= mid) upDate(lson, l, r, val, op);
	if(r > mid) upDate(rson, l, r, val, op);
	sum[rt] = sum[ls] + sum[rs];
	sum1[rt] = sum1[ls] + sum1[rs];
	sum2[rt] = sum2[ls] + sum2[rs];
	sum[rt] %= mod;
	sum1[rt] %= mod;
	sum2[rt] %= mod;
}
ll query(int rt, int L, int R, int l, int r, int op)
{
	if(l <= L && R <= r){
		if(op == 1){
			return sum[rt];
		}
		else if(op == 2){
			return sum1[rt];
		}
		else if(op == 3){
			return sum2[rt];
		}
	}
	ll res = 0ll;
	pushDown(rt,L,R);
	if(l <= mid) res += query(lson,l,r,op);
	if(r > mid) res += query(rson,l,r,op);
	return res%mod;
}
int main()
{
	ll n, m;
	ll a, b, c, d;
	while(~scanf("%lld%lld", &n, &m)){
		if(n==0 && m== 0)break;
		build(1, 1, n);
		for(int i = 0; i < m; i++){
			scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
			if(a == 1){
				upDate(1,1,n,b,c,d,1);
			}
			else if(a == 2){
				upDate(1,1,n,b,c,d,2);
			}
			else if(a == 3){
				upDate(1,1,n,b,c,d,3);
			}
			else if(a == 4){
				ll ans = query(1,1,n,b,c,d);
				printf("%lld\n", ans);
			}
		}
	}
	return 0;
}

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值