#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);} #define MS(x,y) memset(x,y,sizeof(x)) #define MC(x,y) memcpy(x,y,sizeof(x)) #define MP(x,y) make_pair(x,y) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;} template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;} const int N=2e5+10,M=0,Z=1e9+7,ms63=0x3f3f3f3f; int n,m,k,s,x; int f[2][N],d[2][N]; pair<LL,int>p[2][N]; int h[2],t[2];LL v[2]; bool check(int top) { LL tmp=0; h[0]=h[1]=0; for(int i=1;i<=k;++i) { for(int o=0;o<2;++o)v[o]=p[o][h[o]].first*f[o][top]; if(v[0]<v[1]){tmp+=v[0];++h[0];} else {tmp+=v[1];++h[1];} if(tmp>s)return 0; } return 1; } void print(int top) { printf("%d\n",top); h[0]=h[1]=0; for(int i=1;i<=k;++i) { for(int o=0;o<2;++o)v[o]=p[o][h[o]].first*f[o][top]; if(v[0]<v[1]){printf("%d %d\n",p[0][h[0]].second,d[0][top]);++h[0];} else {printf("%d %d\n",p[1][h[1]].second,d[1][top]);++h[1];} } } void solve() { int l=1; int r=n+1; while(l<r) { int mid=(l+r)>>1; if(check(mid))r=mid; else l=mid+1; } if(l==n+1)puts("-1"); else print(l); } int main() { while(~scanf("%d%d%d%d",&n,&m,&k,&s)) { for(int o=0;o<2;++o) { f[o][0]=2e9; for(int i=1;i<=n;++i) { scanf("%d",&x); f[o][i]=f[o][i-1]; d[o][i]=d[o][i-1]; if(x<f[o][i]) { f[o][i]=x; d[o][i]=i; } } } t[0]=t[1]=0; for(int i=1;i<=m;++i) { int o,val; scanf("%d%d",&o,&val);--o; p[o][t[o]++]=MP(val,i); } p[0][t[0]].first=p[1][t[1]].first=2e9; sort(p[0],p[0]+t[0]); sort(p[1],p[1]+t[1]); solve(); } return 0; } /* 【trick&&吐槽】 1,读题读不懂,也要继续沉下心来读题。 否则如果连题意都搞错了,最后是必然要玩完的。 2,保证代码的对称性和结构性是十分好的代码风格,然而千万不要把变量写错QwQ 3,注意排序的时候不要写=号,可能会造成死循环 【题意】 有n(2e5)天时间,初始有s(1e9)元人民币。 每天,我们可以把人民币,根据当天的汇率,兑换成美元或者英镑, 一共有m个物品,而我们需要购买其中的至少k个(1<=k<=m)。 对于每个物品,有两个属性——(对应的货币类型,对应的货币价格)。 货币类型的范围是1或2,表示美元或英镑。货币价格的范围是1e6。 想问你,最早的可以购买k个物品的时刻是? 【类型】 二分答案+贪心 【分析】 首先,我们发现,如果第i天可以购买k个物品,那么第i+1天也一定可以。 也就是说——答案是满足单调性的。于是我们二分答案。 二分答案之后,需要做的就是验证可行性。 首先,我们需要找到前i天的人民币兑换 英镑|美元 的最低价,并找到其对应是哪一天。 这些可以通过预处理得到。 然后,我们对于所有的物品,把其映射对应到其所需要花费的人民币,再把这个按照升序排序。 然后我们贪花费最小的k个,看看所花费的钱是否可以在s范围内即可。 这个时间复杂度其实是有点高的。 我们可以把物品分成两部分,按照它们所对应的货币种类,初始就排好序。 之后就可以类似于归并排序,在O(nlogn)的时间复杂度内AC啦。 【时间复杂度&&优化】 O(nlognlogn)->O(nlogn) */