题目描述
给定一个长度为 nn 的序列 aa,要求支持如下三个操作:
- 给定区间 [l, r],将区间内每个数都修改为 x。
- 给定区间 [l, r],将区间内每个数都加上 x。
- 给定区间 [l, r],求区间内的最大值。
输入格式
第一行是两个整数,依次表示序列的长度 nn 和操作的个数 qq。
第二行有 nn 个整数,第 ii 个整数表示序列中的第 ii 个数 a_iai。
接下来 qq 行,每行表示一个操作。每行首先有一个整数 opop,表示操作的类型。
- 若 op = 1op=1,则接下来有三个整数 l, r, xl,r,x,表示将区间 [l, r][l,r] 内的每个数都修改为 xx。
- 若 op = 2op=2,则接下来有三个整数 l, r, xl,r,x,表示将区间 [l, r][l,r] 内的每个数都加上 xx。
- 若 op = 3op=3,则接下来有两个整数 l, rl,r,表示查询区间 [l, r][l,r] 内的最大值。
输出格式
对于每个 op = 3op=3 的操作,输出一行一个整数表示答案。
输入输出样例
输入 #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复制
4 4 10 4 -3 -7 1 1 3 0 2 3 4 -4 1 2 4 -9 3 1 4输出 #2复制
0说明/提示
数据规模与约定
- 对于 10\%10% 的数据,n = q = 1n=q=1。
- 对于 40\%40% 的数据,n, q \leq 10^3n,q≤103。
- 对于 50\%50% 的数据,0 \leq a_i, x \leq 10^40≤ai,x≤104。
- 对于 60\%60% 的数据,op \neq 1op=1。
- 对于 90\%90% 的数据,n, q \leq 10^5n,q≤105。
- 对于 100\%100% 的数据,1 \leq n, q \leq 10^61≤n,q≤106,1 \leq l, r \leq n1≤l,r≤n,op \in \{1, 2, 3\}op∈{1,2,3},|a_i|, |x| \leq 10^9∣ai∣,∣x∣≤109。
提示
请注意大量数据读入对程序效率造成的影响。
解题思路,对于 修改为x和加上x,可以统一为乘a加b,修改时,a为0,b为x,增加时,a为1,b为x,在线段树中维护a,b和最大值即可。当pushdown时,由于(val*a0+b0)*a1+b1=val*a0*a1+b0*a1+b1,用父区间的a1,b1来更新子区间的a0,b0。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+5; class Node{ public: ll maxn,a,b; ll l,r; }tree[N<<2]; ll arr[N]; void build(int index,ll l,ll r) { tree[index].l=l;tree[index].r=r; tree[index].a=1;tree[index].b=0; if(l==r) { tree[index].maxn=arr[l]; return; } ll mid=l+r>>1; build(index<<1,l,mid); build(index<<1|1,mid+1,r); tree[index].maxn=max(tree[index<<1].maxn,tree[index<<1|1].maxn); } void push_down(int index) { if(tree[index].a==1&&tree[index].b==0)return; tree[index<<1].a*=tree[index].a; tree[index<<1].b=tree[index<<1].b*tree[index].a+tree[index].b; tree[index<<1].maxn=tree[index<<1].maxn*tree[index].a+tree[index].b; tree[index<<1|1].a*=tree[index].a; tree[index<<1|1].b=tree[index<<1|1].b*tree[index].a+tree[index].b; tree[index<<1|1].maxn=tree[index<<1|1].maxn*tree[index].a+tree[index].b; tree[index].a=1;tree[index].b=0; } void update(int index,ll l,ll r,ll x,ll y) { if(tree[index].l>=l&&tree[index].r<=r) { tree[index].a*=x;tree[index].b=tree[index].b*x+y; tree[index].maxn=tree[index].maxn*x+y; return; } push_down(index); if(tree[index<<1].r>=l)update(index<<1,l,r,x,y); if(tree[index<<1|1].l<=r)update(index<<1|1,l,r,x,y); tree[index].maxn=max(tree[index<<1].maxn,tree[index<<1|1].maxn); } ll query(int index,ll l,ll r) { if(tree[index].l>=l&&tree[index].r<=r) { return tree[index].maxn; } push_down(index); ll ans=-1e18; if(tree[index<<1].r>=l)ans=max(ans,query(index<<1,l,r)); if(tree[index<<1|1].l<=r)ans=max(ans,query(index<<1|1,l,r)); return ans; } int main( ) { ios::sync_with_stdio(false); cin.tie(0); ll n;cin>>n;ll m;cin>>m; for(int i=1;i<=n;i++)cin>>arr[i]; build(1,1,n); ll flag,l,r,K; while(m--) { cin>>flag; if(flag==1) { cin>>l>>r>>K; update(1,l,r,0,K); } else if(flag==2) { cin>>l>>r>>K; update(1,l,r,1,K); } else{ cin>>l>>r; cout<<query(1,l,r)<<endl; } } return 0; }