内卷 题解(尺取)

题目链接

题目思路

本赛的时候没看这个题目,其实思路挺简单

但是实现有很多小细节

用尺取法,保证那个区间type==n且typema<=k即可

代码

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const int eps=1e-6;
int n,m,k,ans=inf;
int a[maxn][6];
int vis[maxn][6];
struct node{
    int w,x,y;
}nd[maxn*5];
bool cmp(node a,node b){
    if(a.w!=b.w){
        return a.w<b.w;
    }else{ //保证a等级和其他等级相同时让a等级在后面
        return a.y>b.y;
    }
}
signed main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=5;j++){
            scanf("%d",&a[i][j]);
            nd[++m]={a[i][j],i,j};
        }
    }
    sort(nd+1,nd+1+m,cmp);
    int type=0,typema=0;
    // type 代表有多少个种类
    //  typema代表这个区间有多少个只存在a等级的种类
    for(int l=1,r=0;l<=m;l++){
        if(l!=1){
            vis[nd[l-1].x][nd[l-1].y]=0;
            if(nd[l-1].y==1){
                // 当其中一个人的最大分数都没有了那么肯定凑不齐n个人了
                typema--;
                break;
            }
            int cnt=0;
            for(int i=1;i<=5;i++){
                cnt+=vis[nd[l-1].x][i];
            }
            if(cnt==0){
                type--;
            }else if(cnt==1&&vis[nd[l-1].x][1]){
                //如果只存在一个值,且是最大值那么typema++
                typema++;
            }
        }
        while(r<=m&&type<n&&typema<=k){
            int cnt=0;
            r++;
            vis[nd[r].x][nd[r].y]=1;
            for(int j=1;j<=5;j++){
                cnt+=vis[nd[r].x][j];
            }
            if(cnt==1){
                type++;
                if(nd[r].y==1){
                    typema++;
                }
            }
        }
        if(typema<=k&&type==n){
            ans=min(ans,nd[r].w-nd[l].w);
        }
    }
    printf("%d\n",ans);
    return 0;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/14380884.html