其他分享
首页 > 其他分享> > 洛谷P3933 Chtholly Nota Seniorious

洛谷P3933 Chtholly Nota Seniorious

作者:互联网

题目

https://www.luogu.com.cn/problem/P3933
顺便:中国珂学院

思路

看到此题先大喊一声“我永远喜欢珂朵莉!”

好了然后我们思考一下如何做此题。

我们跳转到问题:现在要问,所有合法的分法中,A区域的极差与B区域的极差 中间较大的一个的最小值是多少?

关键字提取,我们比较容易想到这题大概率是一个二分题,就是求一个最小的\(d\)值使得两部分的极差都\(\leq d\)。

然后我们来看对于某一个\(d\)怎么判定它合不合法。

AAAAA  AAAAA  AAAAA
AABAA  BAAAA  AAABB
ABBBA  BBAAA  AAABB
AABAA  BAAAA  ABBBB
AAAAA  AAAAA  BBBBB
   (1)        (2)         (3)

观察一下切割的规则,发现实际上就是要求每一行\(中A\)的数量单调递减。当然这个结论其实是假的,因为

BBBBA     ABBBB
BBBAA     AABBB
BAAAA     AABBB
BAAAA     AAABB
AAAAA     AAAAB

这些东西也是合法的。

但是可以注意到这些图形通过顺时针旋转\(90°,180°,270°\) 总可以变换到上述的情况。

于是我可以只考虑每行的A单调递减的情况。

那么判定方法也呼之欲出了,我们依次查看每一行,从左往右能分到A就分A,不能就跳到下一行,然后每一行A的上限是上一行A的个数,YY一下可知这种贪心策略是正确的。

这样A的部分就处理完了,然后判一下B的部分极差是否满足就可以了。

保证极差小于d,可以维护一个max和min。

这个题是我高二时联赛前模拟赛的一道题,当时完全没有思路,作为珂学家实在是很丢人qwq。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std;
int a[4][2001][2001];
int check(int k,int n,int m,int d){
    int i,j,L;
    int last[2001],mx=0,mn=inf;
    memset(last,0,sizeof(last));
    last[0]=m;
    for(i=1;i<=n;++i){
        for(j=1;j<=last[i-1];++j){
            if(max(mx,a[k][i][j])-min(mn,a[k][i][j])<=d)
                mx=max(mx,a[k][i][j]),mn=min(mn,a[k][i][j]);
            else
                break;
        }
        last[i]=j-1;
        if(!last[i]) break;
    }
    mn=inf,mx=0;
    for(i=n;i>=1;--i){
        for(j=last[i]+1;j<=m;++j){
            if(max(mx,a[k][i][j])-min(mn,a[k][i][j])<=d)
                mx=max(mx,a[k][i][j]),mn=min(mn,a[k][i][j]);
            else
                return 0;
        }
        if(last[i]==m) return 1;
    }
    return 1;
}
int main(){
    int i,j,n,m,N;
    int ans=inf;
    int mx=0,mn=inf;
    scanf("%d%d",&n,&m);
    N=max(n,m);
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j){
            scanf("%d",&a[0][i][j]);
            a[1][m-j+1][i]=a[0][i][j];
            a[2][n-i+1][m-j+1]=a[0][i][j];
            a[3][j][n-i+1]=a[0][i][j];
            mx=max(mx,a[0][i][j]);
            mn=min(mn,a[0][i][j]);
        }
    }
    int L=0,R=mx-mn;
    while(L<=R){
        int mid=L+R>>1;
        int flag=0;
        flag|=check(0,n,m,mid);
        flag|=check(1,m,n,mid);
        flag|=check(2,n,m,mid);
        flag|=check(3,m,n,mid);
        if(flag) ans=min(ans,mid),R=mid-1;
        else L=mid+1;
    }
    printf("%d",ans);
    // system("pause");
    return 0;
}

标签:Chtholly,洛谷,int,mid,Seniorious,极差,flag,last,check
来源: https://www.cnblogs.com/landmine-sweeper/p/16328019.html