4633. 学生和导师 二分模板题

83 阅读2分钟

4633. 学生和导师 - AcWing题库

题意解读

每个学生ai都要找一个不超过它成绩2倍的导师,假设有多个wi满足条件,那么我们就要找成绩最大的那个导师,即w3。(排个序,最右边的最大): image.png 因此我们可以具有单调性,可以用二分或双指针去做。这里是找最大值,往右走,可以用二分的第二个模板:

image.png

数据范围

image.png

100个样例,每个样例1e51e5,总共1e71e7,因此我们需要一个O(n)O(n)或者O(nlongn)O(nlongn)的算法。二分是O(nlongn)O(nlongn),可以过。

code

假如说我们二分到了自己的导师是自己,说明没有比自己成绩更大的学生了。

因为题目说了自己不能做自己的导师,因此我们需要找一个比自己小的最大成绩的学生做自己的导师,又因为排过序,因此我们只需要向前找一个学生做自己的导师即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],w[N];
int t,n;
int main()
{
     cin>>t;
    for(int Case=1;Case<=t;Case++)
    {
        printf("Case #%d: ",Case);
        cin>>n;
        for(int i=0;i<n;i++)cin>>a[i];
        memcpy(w,a,sizeof a);
        sort(w,w+n);  //排序保证单调性
        
        
        for(int i=0;i<n;i++)
        {
            int l=0,r=n-1;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(w[mid]<=a[i]*2)l=mid;  //二分到的学生是当前学生的2倍之内,我们就要找一个更大的
                else r=mid-1;
            }   
    
            //特判
            if(a[i]==w[r])r--;   //如果二分到的导师就是自己,就找前一位比自己小一点的学生做自己的导师 
            if(r<0)printf("-1 ");  //如果r<0说明自己就是最小的了,再往前找也找不到比自己更小的导师了,那就输出-1
            else printf("%d ",w[r]);
        }
        printf("\n");
    }
    
    return 0;
}