P15263题解

P15263 Circle of Cows P

题目大意

有一个圆和 \(n\) 个特异点,我们需要找 \(m\) 条端点为特异点的弦(端点不能重复),使它们对应劣弧长度的最小值最大。

题目分析

我们考虑到一个性质:选中的弦必定两两相交。

证明:

把每对奶牛连成圆内的弦。设有两条不相交的弦,四个端点按圆周顺序为 \(p_1,p_2,p_3,p_4\),相邻点之间的弧长依次为 \(g_1,g_2,g_3,g_4\)。

原配对 \((p_1,p_2),(p_3,p_4)\) 的距离分别 \(\le g_1\) 和 \(\le g_3\),所以最小值 \(\le \min(g_1,g_3)\)。
改成相交的配对 \((p_1,p_3),(p_2,p_4)\) 后,距离分别是 \(\min(g_1+g_2, g_3+g_4)\) 和 \(\min(g_2+g_3, g_4+g_1)\)。这两个值都 \(\ge \min(g_1,g_3)\)。

所以改成相交的配对不会变差,反复调整后可以假设所有弦两两相交。

由于对于一个选择的弦数量更多的答案,它可以少选择一些弦而保持答案不变,所以我们可以通过做后缀最大值来求答案。

那么我们可以先考虑钦定一条弦为最小的,然后算以它为最短弦求它最多可以选择多少条弦,最后做一个后缀最大值即可。

当钦定了一条弦为最小的的时候,显然我们再选弦的时候,必须一个端点在这条钦定的弦左边,另一个端点在钦定的弦右边,且这条弦长必须大于钦定的弦。所以我们考虑双指针,枚举左端点,并使用一个指针维护右端点。

代码

#include<bits/stdc++.h>
using namespace std;
//#define int long long
const int N=5e5+5;
int n,C;
int a[N];
int getdis(int x,int y)
{
    if(x>n)x-=n;
    if(y>n)y-=n;
    int dis=abs(a[x]-a[y]);
    return min(dis,C-dis);
}
int clac(int x,int y)
{
    int d=getdis(x,y),l=y+1,r=x+n-1,num=1;
    for(int i=x+1;i<=y-1;i++)
    {
        if(l>r)break;
        if(getdis(i,l)<d)while(l<r&&getdis(i,l)<d&&getdis(i,l+1)>getdis(i,l))l++;
        if(getdis(i,l)>=d)num++,l++;
    }
    return num;
}
int ans[N];
int main()
{ 
    cin>>n>>C;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            int num=clac(i,j);
            ans[num]=max(ans[num],getdis(i,j));
        }
    }
    for(int i=n/2;i>=1;i--)ans[i]=max(ans[i],ans[i+1]);
    for(int i=1;i<=n/2;i++)cout<<ans[i]<<' ';
}
posted @ 2026-11-07 16:58  tidewave  阅读(3)  评论(0)    收藏  举报