头像

欢迎来到我的博客

分享题解与总结

P1253 扶苏的问题

P1253 扶苏的问题

题目描述

给定一个长度为 \(n\) 的序列 \(a\),要求支持如下三个操作:

  1. 给定区间 \([l, r]\),将区间内每个数都修改为 \(x\)
  2. 给定区间 \([l, r]\),将区间内每个数都加上 \(x\)
  3. 给定区间 \([l, r]\),求区间内的最大值。

输入格式

第一行是两个整数,依次表示序列的长度 \(n\) 和操作的个数 \(q\)
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列中的第 \(i\) 个数 \(a_i\)
接下来 \(q\) 行,每行表示一个操作。每行首先有一个整数 \(op\),表示操作的类型。

  • \(op = 1\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都修改为 \(x\)
  • \(op = 2\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都加上 \(x\)
  • \(op = 3\),则接下来有两个整数 \(l, r\),表示查询区间 \([l, r]\) 内的最大值。

输出格式

对于每个 \(op = 3\) 的操作,输出一行一个整数表示答案。

输入输出样例 #1

输入 #1

6 6
1 1 4 5 1 4
1 1 2 6
2 3 4 2
3 1 4
3 2 3
1 1 6 -1
3 1 6

输出 #1

7
6
-1

输入输出样例 #2

输入 #2

4 4
10 4 -3 -7
1 1 3 0
2 3 4 -4
1 2 4 -9
3 1 4

输出 #2

0

说明/提示

数据规模与约定

  • 对于 \(10\%\) 的数据,\(n = q = 1\)
  • 对于 \(40\%\) 的数据,\(n, q \leq 10^3\)
  • 对于 \(50\%\) 的数据,\(0 \leq a_i, x \leq 10^4\)
  • 对于 \(60\%\) 的数据,\(op \neq 1\)
  • 对于 \(90\%\) 的数据,\(n, q \leq 10^5\)
  • 对于 \(100\%\) 的数据,\(1 \leq n, q \leq 10^6\)\(1 \leq l, r \leq n\)\(op \in \{1, 2, 3\}\)\(|a_i|, |x| \leq 10^9\)

提示

请注意大量数据读入对程序效率造成的影响。

思路

将范围重置为v → 范围x0+v

将范围增加v → 范围x1+v

双标记分别记录 → 无法判断先后/错误 → 操作合一

P3373 【模板】线段树 2 - 洛谷的启示可以将重置转换为乘法和加法的组合

\(乘法+加法 → {kx+b} 统一操作\)

\(m_1(m_0x+b_0)+b_1=m_1m_2x+(m_1b_0+b_1)\)

\(mtag[p]:m_0 \rightarrow m_1m_0\)

\(atag[p]:b_0 \rightarrow m_1b_0+b_1\)

代码

ll n,a[N];
//区间最大值    mul_tag[p]  add_tag[p]
ll tree[4*N+5],mtag[4*N+5],atag[4*N+5];

void pushup(ll p)
{
	tree[p]=max(tree[2*p],tree[2*p+1]);
}

void addtag(ll p,ll mul,ll add)
{
	tree[p]=tree[p]*mul+add;
	mtag[p]*=mul;
	atag[p]=mul*atag[p]+add;
} 

void build(ll p,ll pl,ll pr)
{
	tree[p]=inf; 
	mtag[p]=1;
	atag[p]=0;
	if(pl==pr){
		tree[p]=a[pl];
		return ;
	}
	ll mid=(pl+pr)>>1;
	build(2*p,pl,mid);
	build(2*p+1,mid+1,pr);
	pushup(p);
}

void pushdown(ll p,ll pl,ll pr)
{
	ll mul=mtag[p],add=atag[p];
	if(mul!=1||add!=0){
		
		addtag(2*p,mul,add);
		
		addtag(2*p+1,mul,add);
		
		mtag[p]=1;
		atag[p]=0;
	}
}

void update(ll p,ll pl,ll pr,ll L,ll R,ll mul,ll add)
{
	if(pr<L||R<pl) return;
	if(L<=pl&&pr<=R){
		addtag(p,mul,add);
		return;
	}
	
	pushdown(p,pl,pr);
	
	ll mid=(pl+pr)>>1;
	update(2*p,pl,mid,L,R,mul,add);
	update(2*p+1,mid+1,pr,L,R,mul,add);
	
	pushup(p);
}

ll query(ll p,ll pl,ll pr,ll L,ll R)
{
	if(pr<L||R<pl) return inf;
	if(L<=pl&&pr<=R) return tree[p];
	
	pushdown(p,pl,pr); 
	
	ll mid=(pl+pr)>>1;
	ll ans=inf;
	ans=max(ans,query(2*p,pl,mid,L,R));
	ans=max(ans,query(2*p+1,mid+1,pr,L,R));
	return ans;
}

int main()
{
	ll q,op,l,r,x;
	scanf("%lld %lld",&n,&q);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
	build(1,1,n); 
	for(int i=1;i<=q;++i){
		scanf("%lld %lld %lld",&op,&l,&r);
		if(op==1){
			scanf("%lld",&x);
            //重置 -> *0+x
			update(1,1,n,l,r,0,x);
		}else if(op==2){
			scanf("%lld",&x);
            //增加 -> *1+x
			update(1,1,n,l,r,1,x);
		}else{
			printf("%lld\n",query(1,1,n,l,r));
		}
	}
	return 0;
}
posted @ 2026-07-25 09:06  king_steph1209  阅读(3)  评论(0)    收藏  举报