整理图书馆
题目描述:
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;
}
易错提醒: