题意
https://vjudge.net/problem/CodeForces-1250B
每个人属于队伍ai,汽车一次至多载两只队伍(全员),费用为车的容量*载人次数,问最少花费。
思路
k(队伍数)只有8000,从这个条件入手这题。先对每个队伍按人数从小到大排序,那么a[k]就是车的最小容量,于是我们可以枚举车的容量i从a[k]开始,用l=1和r=k从两端遍历数组a,如果a[l]+a[r]<=i,那么l++,r--;否则让人数大的队伍先上,即r--。但是如果设车的容量为a[k]+a[k-1],那么会因为很恶心的数据TLE。所以要优化枚举的容量,我们贪心的分配队伍上车,一般都会让人数最多的人数最少的一起上,即a[1]+a[k],a[2]+a[k-1],……只要在这些取最大值就是车容量的上限了。
代码
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=5e5+5; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) ll a[N]; int main() { std::ios::sync_with_stdio(false); ll n,k; cin>>n>>k; for(int i=1; i<=n; i++) { int x; cin>>x; a[x]++; } if(k==1) { cout<<a[1]<<endl; return 0; } ll mx=0; for(int i=1;i<=k;i++) { mx=max(mx,a[i]+a[k-i+1]); } sort(a+1,a+1+k); ll res=1e16; for(ll i=a[k]; i<=mx; i++) { ll l=1,r=k,cnt=0; while(l<r) { cnt++; if(a[l]+a[r]<=i) l++,r--; else r--; } if(l==r) cnt++; res=min(res,i*cnt); } cout<<res<<endl; return 0; }