Inside roll

Insert picture description here
Insert picture description here
Insert picture description here
Idea: Core:
Five grades such as the ruler (dual pointer) are actually useless. Only the number of A grades is restricted in the questions, so the grades are divided into A grades and non-A grades.
To find the minimum difference between the maximum and minimum values, it must be sorted. In what order?
The first keyword is naturally based on the score, and the second keyword is sorted according to whether it is A.
A student who chooses an A score will limit the choice of subsequent students' scores (one less person can choose A), so you can choose a non-A score as far as possible, leaving more choices for latecomers.
The so-called ruler takes, the right pointer does not need to move to the left, because the meaning of the question on the left will be dissatisfied (the number of people selected will be less).
The trouble with this question is that there are more variables to be counted, so be patient when writing.

//尺取
#include <bits/stdc++.h>
#define IOS std::ios_base::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
using namespace std;
typedef long long ll;
const int N=1e5+10;
int numstu=0,numa=0; //选中学生数   仅有A成绩的学生
int stu[N],sa[N];//每个学生被选中的成绩数   每个学生的A成绩是否被选
struct node
{
    
    
    int b,val,num; //b是否为A分数,val分数,num学生
}t[N*5];
bool cmp(node a, node b)//先取非A的分数,给后面的分数留更多的选择余地
{
    
    
    if( a.val != b.val) return a.val<b.val;
    else return a.b<b.b;
}
int main()
{
    
    
    int n,k;
    cin>>n>>k;
    for(int i=1 ;i<=n ;i++)
    {
    
    
        cin>>t[i].val;t[i].b=1;t[i].num=i;
        cin>>t[i+n].val;t[i+n].num=i;
        cin>>t[i+2*n].val;t[i+2*n].num=i;
        cin>>t[i+3*n].val;t[i+3*n].num=i;
        cin>>t[i+4*n].val;t[i+4*n].num=i;
    }
    sort(t+1,t+1+5*n,cmp);
    //  尺取
    int ans=0x7f7f7f7f;
    int j=1;
    //第一个数据入“队”
    stu[t[1].num]++;
    numstu++;
    if( t[1].b==1 )  {
    
    numa++;sa[t[1].num]++;}
    for(int i=1 ;i<=5*n ;i++)
    {
    
    
        while(j<=5*n)
        {
    
    
            //尺取结束条件
            if(numa<=k && numstu==n)
            {
    
    
                ans= min(ans,t[j].val-t[i].val);
                break;
            }
            //右指针只要往右走
            j++;
            stu[t[j].num]++;//学生成绩数++
            if( stu[t[j].num]==1 )  numstu++; //如果成绩是第一次选到,学生++
            if( t[j].b==1 )//如果是A成绩
            {
    
    
                sa[t[j].num]++;
                if(stu[t[j].num]==1 ) numa++;
            }
        }
        stu[t[i].num]--;
        //如果减去后学生成绩数为0,选中学生数--,如果是A成绩,numa--
        if(stu[t[i].num]==0 )
        {
    
    
            numstu--;
            if( t[i].b==1 )    {
    
    numa--;sa[t[i].num]--;}
        }
        if(stu[t[i].num]==1 && sa[t[i].num]==1 ) numa++;
    }
    cout<<ans<<"\n";
}



Guess you like

Origin blog.csdn.net/m0_53688600/article/details/114448972