牛客小白月赛80C/D又放学辣
C
这么小的数据范围,想必胡搞就可以了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,k;
struct cll{
int p;
int id;
}cl[105];
int x;
int ans[205];
bool cmp(cll x,cll y){
return x.p>y.p;
}
void deal(int x){
if(cl[x].p+k>n){
ans[cl[x].id]=-1;
return ;
}
int sum=0;
for(int i=1;i<=m+1;++i){
// if(i==x) continue;
sum=0;
for(int j=1;j<i;++j){
if(j==x) continue;
sum+=cl[j].p;
}
int ex=k-(sum-(i-1-(x<i))*cl[i].p);
if(ex<0){
ans[cl[x].id]=cl[i].p+(-ex)/(i-1-(x<i))+((-ex)%(i-1-(x<i))!=0);
return ;
}else{
if(ex==0){
ans[cl[x].id]=cl[i].p;
return ;
}
}
}
return ;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i){
scanf("%d",&x);
cl[x].p++;
}
for(int i=1;i<=m;++i){
cl[i].id=i;
}
sort(cl+1,cl+m+1,cmp);
for(int i=1;i<=m;++i){
deal(i);
}
for(int i=1;i<=m;++i){
cout<<ans[i]<<" ";
}
return 0;
}
D 数据很大,显然需要对于单个同学log时间内解决,怎么办呢?二分答案。二分答案怎么检查呢?再二分答案。
利用两个二分,就可以在\(o(nlogmlogm)\)时间内解决问题辣。
nclude<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m,k;
int x;
int sum[1000006];
struct cl{
int num;
int id;
}a[1000006];
int ans[1000006];
bool cmp(cl x,cl y){
return x.num<y.num;
}
int bs(int x){
int l=1;
int r=m;
while(l<r){
int mid=(l+r)>>1;
if(a[mid].num>=x) r=mid;
else l=mid+1;
}
return l;
}
bool che(int x,int kk){
int p=bs(kk);
if(p>m) return 1;
else if(p<=x) return sum[p]-a[x].num-(m-p)*(kk-1)-1<k;
else return sum[p]-(m-p+1)*(kk-1)-1<k;
}
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i){
scanf("%d",&x);
a[x].num++;
}
for(int i=1;i<=m;++i)
a[i].id=i;
sort(a+1,a+m+1,cmp);
for(int i=m;i>=1;--i)
sum[i]=sum[i+1]+a[i].num;
for(int i=1;i<=m;++i){
if(a[i].num+k>n){
ans[a[i].id]=-1;
continue;
}
int l=0;
int r=n-a[i].num-k;
while(l<r){
int mid=(l+r+1)>>1;
if(che(i,mid)) r=mid-1;
else l=mid;
}
ans[a[i].id]=l;
}
for(int i=1;i<=m;++i)
cout<<ans[i]<<" ";
return 0;
}