NOIP模拟试题详讲2021/11/4
作者:互联网
又是爆0的一天呢
码风有点点变,可能以后都是这样了qwq
T1
题目大意:有2个序列A,B,可以使某区间加上一个数,每次修改询问 m i n ( m a x ( a 1 , a 2 , a 3 . . . a p , b p + 1 . . . b n ) ∣ 0 ≤ p ≤ n ) min(max(a_1,a_2,a_3...a_p,b_{p+1}...b_n)|0 \leq p\leq n) min(max(a1,a2,a3...ap,bp+1...bn)∣0≤p≤n)。
思路:
我们发现:遍历的顺序是先走A,再走B。
情况1:
红色的代表
[
l
,
r
]
[l,r]
[l,r]区间的最大值,
我们发现如图,若A的最大值在B的最大值得前面,那么无论怎么走,必定要至少经过一个最大值,而题目要求我们求整个区间的最大值的最小值。
那么对于这种情况最小值就是A,B最大值的较小的一个。
情况2:
如果A的最大值在B的最大值的后面。我们发现不好办了。
我们发现L到B的最大值的区域是都要走的,A的最大值到R的区域也是都要走的。
所以我们查询这2段区间的最大值,当然A的最大值,B的最大值也要走,所以还要比较一下A和B的最大值的最小值,对于中间的部分,我们不知道怎么走。
我们可以使用分治思想,重复以上步骤,不断的缩小范围,最后便可得到最后的解。
**核心代码:**注释的部分与下面的是等价的,但下面的更好理解
int solve(int l,int r){
if(l>r) return -inf;
node ma=A.query(1,l,r);
node mb=B.query(1,l,r);
if(ma.pos<=mb.pos) return min(ma.mx,mb.mx);
else{
//if(ma.mx<=mb.mx) return max(A.query(1,l,mb.pos).mx,solve(mb.pos+1,r));
//else return max(B.query(1,ma.pos,r).mx,solve(l,ma.pos-1));
return min(min(ma.mx,mb.mx),max(solve(mb.pos+1,ma.pos-1),max(A.query(1,l,mb.pos).mx,B.query(1,ma.pos,r).mx)));
}
}
对于区间加,我们可以用线段树更新,并且正好也维护区间的最大值,这样问题就解决了。对于线段树封装了一下,其实也差不多,但可以少用一些数组。
代码:
#include<bits/stdc++.h>
using namespace std;
#define lc k<<1
#define rc k<<1|1
//#pragma GCC optimize(2)
#define num ch-'0'
void get(int &res)
{
char ch;bool flag=0;
while(!isdigit(ch=getchar()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getchar());res=res*10+num);
(flag)&&(res=-res);
}
const int N=6e5+5,inf=0x3f3f3f3f;
int n,m,a[N],b[N];
struct node{
int mx,pos;
};
struct TREE{
struct nde{
int l,r,mx,pos,lz;
}t[N<<2];
void pushup(int k){
if(t[lc].mx>=t[rc].mx){
t[k].mx=t[lc].mx;
t[k].pos=t[lc].pos;
}
else{
t[k].mx=t[rc].mx;
t[k].pos=t[rc].pos;
}
}
void pushdown(int k){
if(t[k].lz){
t[lc].mx+=t[k].lz;
t[rc].mx+=t[k].lz;
t[lc].lz+=t[k].lz;
t[rc].lz+=t[k].lz;
t[k].lz=0;
}
}
void build(int k,int l,int r,int cas){
t[k].l=l,t[k].r=r;
if(l==r){
if(cas==1) t[k].mx=a[l];
else t[k].mx=b[l];
t[k].pos=l;
t[k].lz=0;
return;
}
int mid=(l+r)>>1;
build(lc,l,mid,cas);
build(rc,mid+1,r,cas);
pushup(k);
}
void update(int k,int l,int r,int val){
if(t[k].l>=l && t[k].r<=r){
t[k].lz+=val;
t[k].mx+=val;
return;
}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if(l<=mid) update(lc,l,r,val);
if(r>mid) update(rc,l,r,val);
pushup(k);
}
node query(int k,int l,int r){
if(t[k].l>=l && t[k].r<=r) return (node){t[k].mx,t[k].pos};
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
node res,now;res.mx=-inf;
if(l<=mid){
now=query(lc,l,r);
if(res.mx<now.mx){
res.mx=now.mx;
res.pos=now.pos;
}
}
if(r>mid){
now=query(rc,l,r);
if(res.mx<now.mx){
res.mx=now.mx;
res.pos=now.pos;
}
}
return res;
}
}A,B;
int solve(int l,int r){
if(l>r) return -inf;
node ma=A.query(1,l,r);
node mb=B.query(1,l,r);
if(ma.pos<=mb.pos) return min(ma.mx,mb.mx);
else{
//if(ma.mx<=mb.mx) return max(A.query(1,l,mb.pos).mx,solve(mb.pos+1,r));
//else return max(B.query(1,ma.pos,r).mx,solve(l,ma.pos-1));
return min(min(ma.mx,mb.mx),max(solve(mb.pos+1,ma.pos-1),max(A.query(1,l,mb.pos).mx,B.query(1,ma.pos,r).mx)));
}
}
int main(){
//freopen("girl.in","r",stdin);
//freopen("girl.out","w",stdout);
get(n);get(m);
for(int i=1;i<=n;i++) get(a[i]);
for(int i=1;i<=n;i++) get(b[i]);
A.build(1,1,n,1);B.build(1,1,n,2);
char str;int l,r,k;
for(int i=1;i<=m;i++){
cin>>str;
get(l);get(r);get(k);
if(str=='A') A.update(1,l,r,k);
else B.update(1,l,r,k);
get(l);get(r);
cout<<solve(l,r)<<endl;
}
return 0;
}
标签:11,详讲,NOIP,int,res,最大值,pos,lz,mx 来源: https://blog.csdn.net/pigonered/article/details/121151311