http://codeforces.com/contest/767/problem/D
题意:自己已经拥有n瓶牛奶,每瓶保质期已知,超市有m瓶牛奶,保质期已知,每天喝掉k瓶牛奶,不足k瓶全部喝光,过期牛奶就会扔掉,问最多买多少牛奶可以不用扔掉
思路:自然能想到购买的时候贪心的买,从保质期大的开始买,如果保质期大的都需要扔掉,那么自然保质期小的也需要扔掉,那么这个牛奶数目就可以通过二分来check
关键问题这道题数据偏大,如果每次检查答案把所有牛奶拿出来重新排序的话会TLE(可能我写的太菜)
比较优秀的写法是通过最初将b数组排序,每次二分最初购买的位置x,然后检查x-n都购买是否符合要求,check的时候采用双指针,哪一个优小优先选择哪一个,如果一个选完只能选择另一个,然后用一个day记录当前天数,如果现在喝的小于day那么自然不符合要求
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define fi first
#define se second
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<P, int> LP;
const int inf = 0x3f3f3f3f;
const int N = 1e7 + 100;
const ll mod = 1e18+7;
const int base=131;
inline ll mul(ll x,ll y) { return (x*y-(ll)((long double)x*y/mod)*mod+mod)%mod;}
inline ll ksm(ll a,ll b) {ll ans=1;while(b){if(b&1)ans=mul(ans,a);a=mul(a,a),b>>=1;}return ans;}
ll n,m,k,x,y,cx,cy,t;
ll ans,cnt,sum,flag,res;
ll a[N];//,b[N];
ll num[N];
//ll tree[N];
string s;
//vector<int> v[N];
ll mx;
P b[1000005];
bool cmp(P a,P b)
{
return a.fi<b.fi;
}
bool check(ll x)
{
int i=0,j=x,day=0;
int tk=k;
while(i<n||j<m)
{
if(a[i]<b[j].fi&&i<n||j==m)
{
if(a[i]<day) return 0;
tk--;
i++;
}
else
{
if(b[j].fi<day) return 0;
tk--;
j++;
}
//show3(i,j,day)
if(tk==0) day++,tk=k;
}
return 1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>k;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i].fi,b[i].se=i+1;
sort(a,a+n);
sort(b,b+m,cmp);
int l=0,r=m;
ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
if(ans==-1) return cout<<-1,0;
cout<<m-ans<<endl;
for(int i=ans;i<m;i++)
{
cout<<b[i].se<<" ";
}
//cout<<check(0)<<endl;
}
/*
数据范围
是否爆int
空间大小
时间复杂度
*/