二分具体应用

整理图书馆

题目描述:

​ night为了凑够第二课堂学分好顺利毕业,主动申请参加整理图书馆的志愿活动。图书馆中有海量的书,据管理员所说整个图书馆目前有N本书(1​ 花了整整一个下午,night终于把所有的图书按照类型编号以从小到大的顺序整理好了,第一本书的位置编号为1,第二本为2,......,第N本为n。与此同时,管理员来检查了,为了检测night有没有认真地整理图书馆,管理员随意报了一个类型编号S(1

输入描述:

第一行输入2个整数,N,S

第二行输入N个整数,每个整数代表一本书的类型编号,N个数是混乱的状态

输出描述:

若能够找到类型编号为S的书籍,则输出目标书籍的位置编号

若不能找到类型编号为S的书籍,则输出"Not Found"(不输出分号)

输入实例:

5 2 1 2 8 2 2

Copy

输出实例:

3

Copy

数据范围:

对于10%的数据,1对于20%的数据,1对于70%的数据,1

题解:

#include <bits/stdc++.h>
using namespace std;
const int K=1e6+7;
int a[K];
void quicksort(int l,int r){
    if(l>=r) return;
    int i=l-1,j=r+1,x=a[(l+r+1)/2];
    while(i<j){
        do i++;while(a[i]<x);
        do j--;while(a[j]>x);
        if(i<j){
            int t=a[i];
            a[i]=a[j];
            a[j]=t;
        }
    }
    //digui
    quicksort(l,i-1);
 quicksort(i,r);
}
//右边界
int find_r(int *a,int key,int len){
    int l=1,r=len;
    while(l<=r){
        int mid=(r+l)>>1;
        if(a[mid]>key)       r=mid-1;
        else if(a[mid]==key) l=mid+1;
        else if(a[mid]<key)  l=mid+1;
    }
    if(r<=0||a[r]!=key)      return -1;
    return r;
}
//左边界
int find_l(int *a,int key,int len){
    int l=1,r=len;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[mid]<key)       l=mid+1;
        else if(a[mid]==key) r=mid-1;
        else if(a[mid]>key)  r=mid-1;
    }
    if(l>=len||a[l]!=key) return -1;
    else return l;
}
int main(){
    int N,S;
    cin>>N>>S;
    for(int i=1;i<=N;i++){
        cin>>a[i];
    }
    quicksort(1,N);
   // for(int i=1;i<=N;i++){
   //     cout<<a[i]<<" "; }
   if(find_l(a,S,N)==-1||find_r(a,S,N)==-1){
       cout<<"Not Found";
   }else cout<<(find_l(a,S,N)+find_r(a,S,N))/2;
    return 0;
}

木材加工

Description

木材厂有 n 根原木,现在想把这些木头切割成 k 段长度均为 l 的小段木头(木头有可能有剩余。

当然,我们希望得到的小段木头越长越好,请求出 l 的最大值。

木头长度的单位是}cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。

例如有两根原木长度分别为 11 和 21,要求切割成等长的 6 段,很明显能切割出来的小段木头长度最长为 5。

Input

第一行是两个正整数n,k分别表示原木的数量,需要得到的小段的数量。

接下来 n 行,每行一个正整数 L_i,表示一根原木的长度。

Output

仅一行,即 l 的最大值。

如果连 1cm 长的小段都切不出来,输出 0。

Samples

输入数据 1

3 7 232 124 456

Copy

输出数据 1

114

题解:

#include  <bits/stdc++.h>
using namespace std;
const int N =1e6+7;
int a[N];
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    //erfen 
    int l=1,r=1000,ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        int cnt = 0;
        for(int i=1;i<=n;i++){
            cnt+=(a[i]/mid);}
            if(cnt<k) r=mid-1;
            else if(cnt>k)l=mid+1,ans=mid;
            else l=mid+1,ans = mid;
    }
    cout<<ans;

    return 0;
}

小X算排名

说明

小X很关心自己在学校的表现。 

班主任手上有一本“个人得分记录本”,如果一位同学表现好就会加分,表现差则会扣分。学期结束,每位同学都得知了自己的个人得分。小X想知道其他同学情况如何,但由于排名不公布,他只好一个个去问班里的其他同学。 

 现在,小X手上有班里共N位同学的个人得分,他想知道每位同学的排名 (得分相同则排名相同,见样例),可并不知道该如何计算,希望你帮帮他。

输入格式

第一行包含一个整数N。 

接下来N行,第i行包含一个整数Ai,表示第i位同学的得分。

输出格式

N行,第i行包含一个整数,表示第i位同学的排名。

样例

输入数据 1

5 95 100 99 99 96

Copy

输出数据 1

5 1 2 2 4

Copy

提示

数据范围

   对于30%的数据,N≤10。

   对于60%的数据,N≤1000。

   对于 100%的数据,1≤N≤100000,0≤Ai≤100000。

题解:

#include<bits/stdc++.h>
using namespace std;
//从大到小排序,二分查找左边界 over
const int N=1e7;
int a[N],b[N];
int findl(int *a,int key,int len){
    int l=1,r=len;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[mid]==key)     r=mid-1;
        else if(a[mid]<key) r=mid-1;
        else if(a[mid]>key) l=mid+1;
    }
    // if(a[mid]<=key) r=mid-1;
    // else l=mid+1;
    //}     
    return l;
}
bool cmp(int x,int y){
    return x>y;
}
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        cout<<findl(a,b[i],n)<<endl;
    }
    return 0;
}

易错提醒:

猜你喜欢

转载自blog.csdn.net/LuciaX_/article/details/130036465