P1253 扶苏的问题
P1253 扶苏的问题
题目描述
给定一个长度为 \(n\) 的序列 \(a\),要求支持如下三个操作:
- 给定区间 \([l, r]\),将区间内每个数都修改为 \(x\)。
- 给定区间 \([l, r]\),将区间内每个数都加上 \(x\)。
- 给定区间 \([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;
}

浙公网安备 33010602011771号