题意:
有n天,m个工具,至少买k个工具,有s元。第二行第三行是 第一种 硬币 和第二种硬币的汇率。询问最少多少天可以买完。
思路:
二分查找答案,如果可以就左移,否则右移。在查找时,要查询的是在1-》x天内最小的汇率。可以直接排序,nlog,我用的是线段树,logn,感觉好傻。。复杂度分析没注意。。因为会TLE。找到最小汇率,取前k小的工具判断就好了
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=200005;
struct node
{
ll left,right;
ll minn;
}treea[4*maxn],treeb[maxn*4];
ll a[maxn];
ll b[maxn];
ll num[maxn];
ll inf=0x3f3f3f3f;
struct tp
{
int id;
ll price;
}gooda[maxn],goodb[maxn];
int cnta=0,cntb=0;
void builda(int i,int left,int right)
{
treea[i].left=left,treea[i].right=right;
treea[i].minn=inf;
if(left==right)
{
treea[i].minn=a[left];
return ;
}
int mid=(treea[i].left+treea[i].right)>>1;
builda(i<<1,left,mid);
builda(i<<1|1,mid+1,right);
treea[i].minn=min(treea[i<<1].minn,treea[i<<1|1].minn);
return ;
}
void buildb(int i,int left,int right)
{
treeb[i].left=left,treeb[i].right=right;
treeb[i].minn=inf;
if(left==right)
{
treeb[i].minn=b[left];
return ;
}
int mid=(treeb[i].left+treeb[i].right)>>1;
buildb(i<<1,left,mid);
buildb(i<<1|1,mid+1,right);
treeb[i].minn=min(treeb[i<<1].minn,treeb[i<<1|1].minn);
return ;
}
int querya(int i,int left,int right)
{
if(treea[i].left==left&&treea[i].right==right)
{
return treea[i].minn;
}
int mid=(treea[i].left+treea[i].right)>>1;
if(right<=mid)
{
return querya(i<<1,left,right);
}
else if(left>mid)
{
return querya(i<<1|1,left,right);
}
else
{
return min(querya(i<<1,left,mid),querya(i<<1|1,mid+1,right));
}
}
int queryb(int i,int left,int right)
{
if(treeb[i].left==left&&treeb[i].right==right)
{
return treeb[i].minn;
}
int mid=(treeb[i].left+treeb[i].right)>>1;
if(right<=mid)
{
return queryb(i<<1,left,right);
}
else if(left>mid)
{
return queryb(i<<1|1,left,right);
}
else
{
return min(queryb(i<<1,left,mid),queryb(i<<1|1,mid+1,right));
}
}
bool judge(int x,ll mon,int k)
{
ll ma=querya(1,1,x);
ll mb=queryb(1,1,x);
long long res=0;
int num=0;
int flaga=0,flagb=0;
while(num++<k)
{
int op=0;
ll tmp=inf;
if(flaga+1<=cnta)
{
tmp=gooda[flaga+1].price*ma;
op=1;
}
if(flagb+1<=cntb)
{
if(tmp>goodb[flagb+1].price*mb)
{
op=2;
tmp=goodb[flagb+1].price*mb;
}
}
if(op==0)
return false;
if(op==1) flaga++;
else flagb++;
res+=tmp;
if(res>mon)
return false;
}
return true;
}
int cmp(tp x,tp y)
{
return x.price<y.price;
}
int main()
{
ll n,m,k,s;
scanf("%lld%lld%lld%lld",&n,&m,&k,&s);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
for(int i=1;i<=m;i++)
{
int t;
scanf("%d",&t);
if(t==1)
{
scanf("%lld",&gooda[++cnta].price);
gooda[cnta].id=i;
}
else
{
scanf("%lld",&goodb[++cntb].price);
goodb[cntb].id=i;
}
}
sort(gooda+1,gooda+1+cnta,cmp);
sort(goodb+1,goodb+1+cntb,cmp);
builda(1,1,n);
buildb(1,1,n);
int ans=-1;
int l=1,r=n;
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid,s,k))
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
if(ans==-1)
printf("-1\n");
else
{
printf("%d\n",ans);
int ansa=0,ansb=0;
ll ma=querya(1,1,ans);
ll mb=queryb(1,1,ans);
for(int i=1;i<=ans;i++)
{
if(a[i]==ma)
ansa=i;
if(b[i]==mb)
ansb=i;
}
int num=0;
int flaga=0,flagb=0;
while(num++<k)
{
int op=0;
ll tmp=inf;
if(flaga+1<=cnta)
{
op=1;
tmp=ma*gooda[flaga+1].price;
}
if(flagb+1<=cntb)
{
if(tmp>mb*goodb[flagb+1].price)
{
op=2;
}
}
if(op==1)
{
printf("%d %d",gooda[flaga+1].id,ansa);
flaga++;
}
else
{
printf("%d %d",goodb[flagb+1].id,ansb);
flagb++;
}
printf("\n");
}
}
}