P14378 【MX-S9-T1】「LAOI-16」签到题解

P14378 【MX-S9-T1】「LAOI-16」签到

好想不好写!

简单贪心思路就是,小的数尽可能对应大的数,这样序列一个从小到大,一个从大到小。

一个数修改,只会使他当前位置到新到达的位置中间的数挪动,区间以外的其他数不动,区间内的数相当于整体平移对应,然后建线段树求平移后区间最大值最小值,\(a[i+1]+b[i]\)\(a[i-1]+b[i]\)

注意二分部分,这点很重要,要动脑子仔细思考为什么这么二分区间。

#include<bits/stdc++.h>
#define ll long long
//#define int ll
#define ls p<<1
#define rs p<<1|1
#define re register 
#define pb push_back
#define pir pair<int,int> 
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
#define lowbit(x) (x&-x)
using namespace std;
const int N=1e7+10;
const int M=5e6+10;
const int mod=1e9+7;
const int INF=1e9+7;
mt19937 rnd(251);

int n,k,q;
int a[N];
int b[N];
int c[N];
int cnt=0;

int pre_max[N];
int pre_min[N];

int suf_max[N];
int suf_min[N];

int t1_max[N];//a[l+1]+b[l]
int t1_min[N];
int t2_max[N];//a[l-1]+b[l]
int t2_min[N];

bool cmp(int g,int h){
	return g>h;
}

void build(int p,int l,int r){
	if(l==r){
		t1_max[p]=a[l+1]+b[l];
		t1_min[p]=a[l+1]+b[l];
		
		t2_max[p]=a[l-1]+b[l];
		t2_min[p]=a[l-1]+b[l];
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	
	t1_max[p]=max(t1_max[ls],t1_max[rs]);
	t1_min[p]=min(t1_min[ls],t1_min[rs]);
	
	t2_max[p]=max(t2_max[ls],t2_max[rs]);
	t2_min[p]=min(t2_min[ls],t2_min[rs]);		
}

int query_max1(int p,int pl,int pr,int l,int r){
	if(l<=pl&&pr<=r){
		return t1_max[p];
	}
	int mid=(pl+pr)>>1;
	int ans=0;
	if(l<=mid){
		ans=max(ans,query_max1(ls,pl,mid,l,r));
	}
	if(r>mid){
		ans=max(ans,query_max1(rs,mid+1,pr,l,r));
	}
	return ans;
}
int query_max2(int p,int pl,int pr,int l,int r){
	if(l<=pl&&pr<=r){
		return t2_max[p];
	}
	int mid=(pl+pr)>>1;
	int ans=0;
	if(l<=mid){
		ans=max(ans,query_max2(ls,pl,mid,l,r));
	}
	if(r>mid){
		ans=max(ans,query_max2(rs,mid+1,pr,l,r));
	}
	return ans;
}

int query_min1(int p,int pl,int pr,int l,int r){
	if(l<=pl&&pr<=r){
		return t1_min[p];
	}
	int mid=(pl+pr)>>1;
	int ans=INF;
	if(l<=mid){
		ans=min(ans,query_min1(ls,pl,mid,l,r));
	}
	if(r>mid){
		ans=min(ans,query_min1(rs,mid+1,pr,l,r));
	}
	return ans;
}

int query_min2(int p,int pl,int pr,int l,int r){
	if(l<=pl&&pr<=r){
		return t2_min[p];
	}
	int mid=(pl+pr)>>1;
	int ans=INF;
	if(l<=mid){
		ans=min(ans,query_min2(ls,pl,mid,l,r));
	}
	if(r>mid){
		ans=min(ans,query_min2(rs,mid+1,pr,l,r));
	}
	return ans;
}

void solve(){
	cin>>n>>k>>q;
	
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	
	for(int i=1;i<=k;i++){
		cin>>c[i];
	}
	for(int i=1;i<=k;i++){
		int x;
		cin>>x;
		for(int j=1;j<=c[i];j++){
			b[++cnt]=x;
		}
	}
	
	for(int i=1;i<=n;i++){
		c[i]=a[i];
	}
	
	sort(a+1,a+1+n);
	sort(b+1,b+1+n,cmp);
	
	//前缀 
	pre_min[0]=INF;
	for(int i=1;i<=n;i++){
		pre_max[i]=max(pre_max[i-1],a[i]+b[i]);
		pre_min[i]=min(pre_min[i-1],a[i]+b[i]);
	}
	//后缀 
	suf_min[n+1]=INF;
	for(int i=n;i>=1;i--){
		suf_max[i]=max(suf_max[i+1],a[i]+b[i]);
		suf_min[i]=min(suf_min[i+1],a[i]+b[i]);
	}
	
	build(1,1,n);
	
	for(int i=1;i<=q;i++){
		int x,y;
		cin>>x>>y;
		
		k=c[x];
		
		if(k==y){
			cout<<pre_max[n]-pre_min[n]<<"\n";
			continue; 
		}
		
		int l,r;
		int mx=0,mi=INF;
		
		if(k<=y){
			l=upper_bound(a+1,a+1+n,k)-a-1;
			r=lower_bound(a+1,a+1+n,y)-a-1;
			l=max(l,1);
			r=min(r,n);
			
			mx=max(mx,query_max1(1,1,n,l,r-1));
			mx=max(mx,y+b[r]);
			
			mi=min(mi,query_min1(1,1,n,l,r-1));
			mi=min(mi,y+b[r]);
		}
		else{
			l=upper_bound(a+1,a+1+n,y)-a;
			r=lower_bound(a+1,a+1+n,k)-a;
			l=max(l,1);
			r=min(r,n);
			
			mx=max(mx,query_max2(1,1,n,l+1,r));
			mx=max(mx,y+b[l]);
			
			mi=min(mi,query_min2(1,1,n,l+1,r));
			mi=min(mi,y+b[l]);	
		}
		mx=max(mx,pre_max[l-1]);
		mx=max(mx,suf_max[r+1]);
			
		mi=min(mi,pre_min[l-1]);
		mi=min(mi,suf_min[r+1]);
		
//		cout<<l<<" "<<r<<"\n";
//		cout<<"ans=";
		cout<<mx-mi<<"\n";
	}
}



signed main(){
//  	freopen("replace4.in","r",stdin);
//  	freopen("a.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(nullptr);   
    
    solve();
	
    return 0;
}
posted @ 2025-11-14 13:54  sad_lin  阅读(4)  评论(0)    收藏  举报