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
空間大小
時間複雜度
*/