一年一度的鸭子比赛开始了,有 只鸭子参加了本次比赛,比赛是两两淘汰赛制。其中,第 只鸭子在鸭群中的排名为 ,如果2只鸭子的的排名之差 ,一定是排名高的赢,否则不一定。
现在鸭子们已经准备好了比赛,请问可能夺冠的选手当中,排名最后的是多少号?
最难的题目
二分+贪心
// luogu-judger-enable-o2
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
bool a[18010];
vector<int>q;
int n,k;
int find(int x){
for(int i=max(x-k,1);i<=n;i++)
if(a[i]){
a[i]=false;
return i;
}
return -1;
}
bool check(int x){
memset(a,1,sizeof(a));
q.clear();
q.push_back(x);
a[x]=0;
int beg=1;
while(beg<n)
for(int j=0;j<q.size();j++){
beg++;
x=find(q[j]);
if(x==-1)return false;
q.insert(j+q.begin()+1,x);
j++;
}
return true;
}
int main(){
cin>>n>>k;
int left=1,right=n+1;
while(left+1<right){
int mid=(left+right)/2;
if(check(mid))left=mid;
else right=mid;
}cout<<left;
return 0;
}
// luogu-judger-enable-o2
#pragma GCC optimize(3)
这个是个好东西,让我最后一个点的时间,减少了一半,从TLE变成AC
洛谷神鸭
竟然用了并查集
我仔细想了一下,确实是一个好方法,在这也放一下代码
#include<bits/stdc++.h>
using namespace std;
template <typename T> inline void read(T &FF)
{
int RR=1;FF=0;char CH=getchar();
while(!isdigit(CH)&&CH!='-') CH=getchar();
if(CH=='-') RR=-1;else FF=CH^48;CH=getchar();
while(isdigit(CH)) FF=(FF<<1)+(FF<<3)+(CH^48),CH=getchar(); FF*=RR;
}
int n,k,ans;
int fa[100010];
int bcj(int xi)
{
if(xi==-1) return xi;
if(fa[xi]==xi) return xi;
return fa[xi]=bcj(fa[xi]);
}
bool work(int i)
{
for(int l=1;l<=n;l++)
fa[l]=l;
fa[n+1]=-1;
fa[i]=(i==n)?-1:i+1;
deque<int> qi; int o=1;
qi.push_front(i);
while(o<n)
{
int stp=qi.back();
while(qi.front()!=stp)
{
o++;
int pi=qi.front(); qi.pop_front(); qi.push_back(pi);
int Ty=bcj(max(pi-k,1));
if(Ty==-1) return false;
qi.push_back(Ty),fa[Ty]=bcj(Ty+1);
}
o++;
int pi=qi.front(); qi.pop_front(); qi.push_back(pi);
int Ty=bcj(max(pi-k,1));
if(Ty==-1) return false;
qi.push_back(Ty),fa[Ty]=bcj(Ty+1);
}
return true;
}
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
read(n),read(k);
int l=1,r=n;
while(l<=r)
{
//memset(flag,0,sizeof(flag));
int mid=(l+r)>>1;
if(work(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans<<endl;
return 0;
}
并查集真强大,我开 用时还是他的代码的10
倍左右