Codeforces 609D 被二分教做人

传送门:http://codeforces.com/problemset/problem/609/D

(如需转载,请注明出处,谢谢O(_)O

题意:

Nura想买k个小玩意,她手上有 s 个burles(一种货币),有m个小玩意供她选择购买,但每个小玩意只能用dollars或者pounds来购买,所以每次购买的时候Nura都要通过汇率将她手上的burles换成dollars或者pounds,而每一天的汇率又不一样,给出n天,并且这n天中burles换成dollars和pounds的比率,问是否能在这n天中用手上的burles买下k个小玩意,如果不能,输出-1;如果能,输出最小的天数(即能使得Nura买下k个小玩意的最少天数),并在接下来的m行中,依次输出两个数字,分别是买下的小玩意的编号(按给出的顺序编号)以及买下该小玩意的日期(即第几天)。——在同一天中可以买任意多个小玩意。

解题思路与分析:

注意到数据范围是2e5,而显然需要通过某种方式来比较“天数”,直接枚举肯定很虚,所以要用到二分。

(这里给出同学写的二分的正确姿势:

int L,R,M;

while(R-L>1){

M=((R-L)>>1)+L;

if() R=M;

else L=M;

}

确定了用二分来枚举天数之后,就需要确定二分里面的内容。因为一天可以买多个,所以显然应该找兑换率最高的一天,即区间最小值,这里用了ST算法,O(nlogn)预处理,O(1)查询——获得了区间里burles兑换dollars和pounds最“划算”的一天后,就是确定买下k个小玩意的最小花费了,这里没有想到更简便的方法,只能用了O(mlogm)的预处理(排序),每次O(k)获取花费。用结构体存储小玩意的type,cost以及num(编号,后面输出用到),然后排序——重载小于号,先按type排,再按cost排,记录type==2的第一个小玩意对应的下标ter,之后只需要每次计算的时候比较一下,就能保证获取最小花费了(细节见代码)——获取最小花费后,将之与s比较一下即可知该区间是否可行。

代码实现过程与反思:

感觉基本上坑被踩了个尽。。

1、计算最小花费的时候,会造成int溢出,要用long long。

2、不是坑的坑:原题output部分中的”number of gadget”,是指小玩意的编号,不是数目(gadget没有s),醉。

4、细节:计算最小花费的时候,while循环应为j<m而不为j<n(j为ter为起点的下标,i从0开始),又wa一发。。

3、二分的时候,因为while中的是R-L>1,所以当n为1时,将直接跳过二分判断。并且,如果存在可行的答案,其必然为二分循环结束后的L或者R,先判L,如果L不行就判断R;如果都不行,说明不存在正确结果。这里又wa了几发,,被二分教做人。

代码如下:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 typedef long long ll;
  7 const int N=2e5+10,M=15;
  8 struct gadget{
  9     int type,cost,num;
 10     bool operator < (const gadget g) const{
 11         return type==g.type?cost<g.cost:type<g.type;
 12     }
 13 }G[N];
 14 int n,m,k,s,ter,a[N],b[N],da[N][M],db[N][M];
 15 void init(){
 16     for(int i=0;i<n;i++) da[i][0]=a[i],db[i][0]=b[i];
 17     for(int j=1;(1<<j)<=n;j++)
 18         for(int i=0;i+(1<<j)-1<n;i++){
 19             da[i][j]=min(da[i][j-1],da[i+(1<<(j-1))][j-1]);
 20             db[i][j]=min(db[i][j-1],db[i+(1<<(j-1))][j-1]);
 21         }
 22 }
 23 int RMQ(int L,int R,int d[N][M]){
 24     int k=0;
 25     while((1<<(k+1))<=R-L+1) k++;
 26     return min(d[L][k],d[R-(1<<k)+1][k]);
 27 }
 28 bool check(ll p1,ll p2){
 29     int cnt=0;
 30     ll tot=0;
 31     int i=0,j=ter;
 32     while(j<m){
 33         if(i==ter||cnt==k) break;
 34         if(G[i].cost*p1<=G[j].cost*p2)
 35             tot+=G[i++].cost*p1;
 36         else tot+=G[j++].cost*p2;
 37         cnt++;
 38     }
 39     if(cnt<k){
 40         if(i<ter) swap(i,j),swap(p1,p2);
 41         while(cnt<k) tot+=p2*G[j++].cost,cnt++;
 42     }
 43     return tot<=s;
 44 }
 45 int main(){
 46     //freopen("in.txt","r",stdin);
 47     while(~scanf("%d%d%d%d",&n,&m,&k,&s)){
 48         for(int i=0;i<n;i++)
 49             scanf("%d",a+i);
 50         for(int i=0;i<n;i++)
 51             scanf("%d",b+i);
 52         ter=0;
 53         for(int i=0;i<m;i++){
 54             scanf("%d%d",&G[i].type,&G[i].cost);
 55             if(G[i].type==1) ter++;
 56             G[i].num=i+1;
 57         }
 58         init();
 59         sort(G,G+m);
 60         bool flag=false;
 61         int L=0,R=n-1,mid;
 62         ll p1,p2;
 63         while(R-L>1){
 64             mid=((R-L)>>1)+L;
 65             p1=RMQ(0,mid,da),p2=RMQ(0,mid,db);
 66             if(check(p1,p2)) R=mid;
 67             else L=mid;
 68         }
 69         p1=RMQ(0,L,da),p2=RMQ(0,L,db);
 70         if(check(p1,p2)) flag=true;
 71         else{
 72             p1=RMQ(0,R,da),p2=RMQ(0,R,db);
 73             if(check(p1,p2)) flag=true;
 74         }
 75         if(flag){
 76             int d1,d2;
 77             for(int i=0;i<n;i++) if(a[i]==p1){
 78                 d1=i+1;break;
 79             }
 80             for(int i=0;i<n;i++) if(b[i]==p2){
 81                 d2=i+1;break;
 82             }
 83             printf("%d\n",max(d1,d2));
 84             int cnt=0,tot=0;
 85             int i=0,j=ter;
 86             while(j<m){
 87                 if(i==ter||cnt==k) break;
 88                 if(G[i].cost*p1<=G[j].cost*p2){
 89                     cnt++;
 90                     printf("%d %d\n",G[i++].num,d1);
 91                 }
 92                 else{
 93                     cnt++;
 94                     printf("%d %d\n",G[j++].num,d2);
 95                 }
 96             }
 97             if(cnt<k){
 98                 if(i<ter) swap(d1,d2),swap(i,j);
 99                 while(cnt<k) printf("%d %d\n",G[j++].num,d2),cnt++;
100             }
101         }
102         else puts("-1");
103     }
104     return 0;
105 }

时间: 2024-10-05 04:28:10

Codeforces 609D 被二分教做人的相关文章

Codeforces 1165F2(二分内的check)

要点 二分答案,内部喜闻乐见的拖延策略:对于某个打折玩具,就选最晚的打折时间买,答案并不会变劣,只是购买时间的平移. 注意最晚时间不是预处理的东西,是二分内部的.在mid以内的最晚时间. #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int maxn = 2e5 + 5; int n, m, k[maxn], d[maxn], t[maxn]; in

从30岁至35岁:为你的生命多积累一些厚度

你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇:你所有曾经潇洒的随遇而安,同样也会随时间流逝而让你承担那些似乎命中已经注定的代价.在这 个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变 着一切.”我始终相信一句话:出来混,迟早要还的.虽然你我皆是凡人,只是这芸芸众生中的普通一员,但我依然希望每个人的生命都能够迎着太阳开花结果.不 管以你现在的阅历是否能够理解这段话的涵义,请先记下来.我相信总

职场35岁现象:职业规划的文章 [转]

在这个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变着一切.” 我始终相信一句话:出来混,迟早要还的. 虽然你我皆是凡人,只是这芸芸众生中的普通一员,但我依然希望每个人的生命都能够迎着太阳开花结果.不管以你现在的阅历是否能够理解这段话的涵义,请先记下来. 我相信总有一天,你会明白. 因为,时间能解释一切,时间能证明一切,时间能解决一切. 在最近的一年的职业规划咨询过程中,我明显地感觉到35岁以上人群对

从30岁到35岁:为你的生命多积累一些厚度(转)

从30岁到35岁:为你的生命多积累一些厚度(转) 常常思考一个问题:是不是考虑做2年开发,打2年酱油,然后结婚生子,这样到底行不行?无论你是男是女,人生是一场独自修行的道路.如果在可以选的时候,还是选择靠自己吧. 无论你是要养家还是要实现人生价值,如果你处在迷茫之中,希望这篇文章可以传达一些正能量,可以帮到你.--当然这篇文章是转的呀,但真的很有理啊,假如看了这篇文章,会影响到你的一生,那么我就觉得今天这一小时的时间花在这里值了. 你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇:你所有

从30岁到35岁:为你的生命多积累一些厚度(转)

你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇:你所有曾经潇洒的随遇而安,同样也会随时间流逝而让你承担 那些似乎命中已经注定的代价.在这 个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变 着一切.”我始终相信一句话:出来混,迟早要还的.虽然你我皆是凡人,只是这芸芸众生中的普通一员,但我依然希望每个人的生命都能够迎着太阳开花结果.不 管以你现在的阅历是否能够理解这段话的涵义,请先记下来.我相信

老板为何喜欢坐头等舱,空姐透露的“潜规则”

  坐飞机的一个现象 观察30到40这个年纪的旅客,头等舱的旅客往往是在看书,公务舱的旅客大多看杂志用笔记本办公,经济舱则看报纸电影玩游戏和聊天的较多.在机场,贵宾厅里面的人大多在阅读,而普通候机区全都在玩手机.那么,到底是人的位置影响了行为呢,还是行为影响了位置呢? 茶叶的小故事 张三一直喜欢喝20块钱的茶叶.新开茶店里每次张三去买茶叶,老板都送他半两好茶.张三将好茶攒着待客.一天闲来无事泡壶好茶,竟喝上瘾.喝完免费的好茶,张三便不愿喝20块的了.不管他买多贵的茶叶,老板总送他半两更好的.半年

从30岁到35岁:为你的生命多积累一些厚度

你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇:你所有曾经潇洒的随遇而安,同样也会随时间流逝而让你承担那些似乎命中已经注定的代价.在这 个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变 着一切.”我始终相信一句话:出来混,迟早要还的.虽然你我皆是凡人,只是这芸芸众生中的普通一员,但我依然希望每个人的生命都能够迎着太阳开花结果.不 管以你现在的阅历是否能够理解这段话的涵义,请先记下来.我相信总

从30岁到35岁:为你的生命多积累一些厚度【转载】

你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇:你所有曾经潇洒的随遇而安,同样也会随时间流逝而让你承担那些似乎命中已经注定的代价.在这 个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变 着一切.”我始终相信一句话:出来混,迟早要还的.虽然你我皆是凡人,只是这芸芸众生中的普通一员,但我依然希望每个人的生命都能够迎着太阳开花结果.不 管以你现在的阅历是否能够理解这段话的涵义,请先记下来.我相信总

写给30岁的自己

在这个世界上,“唯一不可阻挡的是时间,它像一把利刃,无声地切开了坚硬和柔软的一切,恒定地向前推进着,没有任何东西能够使它的行进产生丝毫颠簸,它却改变着一切.” 一.每个人都会遇到的“35岁现象” 不管你是否承认,你都必须重视“35岁现象”.很多企业在招募人才时,明确规定年龄在35岁以下.如果你的年龄到了35岁却还在通过招聘网站投递简历不断跳槽的话,你就应该反省一下自己到底哪里做错了.当然,根据我们的实践咨询经验来看,如果你真到了35岁甚至更高的年龄才去思考这个问题,很有可能这个问题你已经无力解决