ARC66 D Interval Counts 题解

发布时间 2023-11-26 00:10:37作者: Martian148

Link

ARC66 D Interval Counts

Question

给定正整数 \(n\) 和长度为 \(n\) 的序列 \(x_i,y_i\) 保证 \(x_i\) 单调递增,你需要构造 \(m\) 个去年 \([L_i,R_i]\)\(m\) 有你指定,使得每个 \(x_i\)恰好被 \(y_i\) 个区间包含

最大化 \(min({R_i-L_i})\),并求其值

Solution

贪心的去做,一段区间需要尽可能的大,需要满足

  • 从一个 \(x_i+1\) 开始
  • 到一个 \(x_i-1\) 结束
  • 先开始的先结束,后开始的后结束

有了这三点思想,我们就可以用队列来模拟这个过程

  • 如果 \(y_i= y_{i-1}\) 我们不需要做,把上一段的延长过来就好了
  • 如果 \(y_i>y_{i-1}\) 我们需要从 \(x_{i-1}+1\) 开始,补一些边
  • 如果 \(y_i < y_{i-1}\) 那么我们需要断一些变,断边的顺序就是加边的顺序

我们不可能一条一条的加边,考虑到一部分边的起始点和终止点都是相同的,所以用二元组 \((pos,number)\) 维护就好了

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5,INF=1e9;
struct node{
    int pos,number;
};
int N,X[maxn],Y[maxn],hed=1,til,ans=INF;
node q[maxn];
inline int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int main(){
    freopen("D.in","r",stdin);
    freopen("D.out","w",stdout);
    N=read();
    for(int i=1;i<=N;i++) X[i]=read();
    for(int i=1;i<=N;i++) Y[i]=read();
    X[0]=-INF;
    for(int i=1;i<=N;i++){
        if(Y[i]==Y[i-1]) continue;
        if(Y[i]>Y[i-1]) q[++til]=(node){X[i-1]+1,Y[i]-Y[i-1]};
        else {
            int now=Y[i-1]-Y[i];
            while(hed<=til&&q[hed].number<=now){
                ans = min(ans,X[i]-q[hed].pos);
                now -= q[hed].number;
                hed++;
            }
            if(hed<=til&&q[hed].number>now&&now) {
                q[hed].number-=now;now=0;
                ans=min(ans,X[i]-q[hed].pos);
            }
        }
    }
    if(ans==INF)printf("-1\n");
    else printf("%d\n",ans-1);
    return 0;
}