看了菊苣的理解才知道怎么写。。根本没思路啊一开始。。。
天数肯定在1~n之间,二分答案。
可以用保存前i天的最低美元和英镑汇率,没有规定哪天买,每天也没有购买数量限制,所以二分出一个答案mid的后,就在前mid天中汇率最低的时候一次性购入最便宜的就行了,judge一下总花费
打印答案的时候以ans为结果,再模拟一遍就好
#include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include"cstring" #include"queue" #include"vector" #define ll long long using namespace std; const int MAXN = 200050; const int INF = 0x3f3f3f3f; ll n,m,k,s; ll d[MAXN],p[MAXN],mind[MAXN],minp[MAXN]; int mindpos[MAXN],minppos[MAXN]; struct node{ ll c,o; node(){} node(ll a,ll b):c(a),o(b){} }; vector<node> dd,pp; bool cmp(node a,node b){ return a.c<b.c; } bool judge(ll x){ ll tot=0,cnt=0; int i=0,j=0; while(cnt<k&&tot<=s){ ll td=INF,tp=INF; if(i<dd.size()) td=mind[x]*dd[i].c; if(j<pp.size()) tp=minp[x]*pp[j].c; if(td<tp){ tot+=td; i++; } else{ tot+=tp; j++; } cnt++; } if(tot>s) return false; return true; } void display(ll ans){ if(ans==-1) return ; ll cnt=1; int i=0,j=0; while(cnt<=k){ ll td=INF,tp=INF; if(i<dd.size()) td=mind[ans]*dd[i].c; if(j<pp.size()) tp=minp[ans]*pp[j].c; if(td<tp) printf("%I64d %d ",dd[i++].o,mindpos[ans]); else printf("%I64d %d ",pp[j++].o,minppos[ans]); cnt++; } } int main(){ //freopen("in.txt","r",stdin); scanf("%I64d%I64d%I64d%I64d",&n,&m,&k,&s); minp[0]=mind[0]=INF; for(int i=1;i<=n;i++) { scanf("%I64d",&d[i]); mind[i]=min(mind[i-1],d[i]); if(mind[i]!=mind[i-1]) mindpos[i]=i; else mindpos[i]=mindpos[i-1]; } for(int i=1;i<=n;i++) { scanf("%I64d",&p[i]); minp[i]=min(minp[i-1],p[i]); if(minp[i]!=minp[i-1]) minppos[i]=i; else minppos[i]=minppos[i-1]; } for(int i=1;i<=m;i++) { ll t,c; scanf("%I64d%I64d",&t,&c); if(t==1) { dd.push_back(node(c,i)); } else pp.push_back(node(c,i)); } sort(dd.begin(),dd.end(),cmp); sort(pp.begin(),pp.end(),cmp); //for(int i=1;i<=n;i++) cout<<mindpos[i]<<' '<<minppos[i]<<endl; ll low=1,high=n,mid,ans=-1; while(low<=high){ mid=(low+high)>>1; if(judge(mid)){ ans=mid; high=mid-1; } else low=mid+1; } printf("%I64d ",ans); display(ans); return 0; }