题目链接:https://codeforces.com/contest/1435/problem/C
给定 \(n\) 个 \(b_i\),每个 \(b_i\) 可以选择减去\(a_{1,\ldots,6}\)中的一个数字,求新数列中最大值减最小值的最小值
题意很绕,需要仔细理解
将所有的二元组\((b_i-j,i)\),按关键字排好序,双指针扫一遍,当满足位置\(1,\ldots,n\)都出现过以后,更新答案
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 100100;
int n,cnt;
int a[10],b[maxn];
pair<int,int> P[6*maxn];
struct SEG{
int mi,add;
}t[maxn<<2];
bool cmp(pair<int,int> x,pair<int,int> y){
if(x.first == y.first){
return x.second < y.second;
}else{
return x.first < y.first;
}
}
void pushup(int i){ t[i].mi = min(t[i<<1].mi,t[i<<1|1].mi); }
void mdf(int i,int k,int l,int r,int p){
if(l == r){
t[i].mi += k;
return;
}
int mid = (l+r)/2;
if(p<=mid) mdf(i<<1,k,l,mid,p);
else mdf(i<<1|1,k,mid+1,r,p);
pushup(i);
}
int qry(int i,int l,int r,int x,int y){
if(x <= l && r <= y){
return t[i].mi;
}
int mid = (l+r)/2;
int mi = 1000000007;
if(x <= mid) mi = min(mi,qry(i<<1,l,mid,x,y));
if(y > mid) mi = min(mi,qry(i<<1|1,mid+1,r,x,y));
return mi;
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
for(int i=1;i<=6;++i) a[i] = read();
n = read(); cnt = 0;
for(int i=1;i<=n;++i){
b[i] = read();
for(int j=1;j<=6;++j){
P[++cnt].first = b[i] - a[j];
P[cnt].second = i;
}
}
sort(P+1,P+1+cnt,cmp);
int ans = 1000000007;
for(int l = 0,r = 0; l < cnt; ++l){
while((qry(1,1,n,1,n) == 0 && r < cnt)){
++r;
mdf(1,1,1,n,P[r].second);
}
if(qry(1,1,n,1,n) != 0) ans = min(ans,P[r].first - P[l+1].first);
if(l==r){
++r;
mdf(1,1,1,n,P[r].second);
}
mdf(1,-1,1,n,P[l+1].second);
}
printf("%d\n",ans);
return 0;
}