D. Too Easy Problems(思维+二分枚举)

104 篇文章 0 订阅
62 篇文章 2 订阅

https://codeforces.com/problemset/problem/913/D


 

题目描述

You are preparing for an exam on scheduling theory. The exam will last for exactly TT milliseconds and will consist of nn problems. You can either solve problem ii in exactly t_{i}ti​ milliseconds or ignore it and spend no time. You don't need time to rest after solving a problem, either.

Unfortunately, your teacher considers some of the problems too easy for you. Thus, he assigned an integer a_{i}ai​ to every problem ii meaning that the problem ii can bring you a point to the final score only in case you have solved no more than a_{i}ai​ problems overall (including problem ii ).

Formally, suppose you solve problems p_{1},p_{2},...,p_{k}p1​,p2​,...,pk​ during the exam. Then, your final score ss will be equal to the number of values of jj between 1 and kk such that k<=a_{pj}k<=apj​ .

You have guessed that the real first problem of the exam is already in front of you. Therefore, you want to choose a set of problems to solve during the exam maximizing your final score in advance. Don't forget that the exam is limited in time, and you must have enough time to solve all chosen problems. If there exist different sets of problems leading to the maximum final score, any of them will do.

输入格式

The first line contains two integers nn and TT ( 1<=n<=2·10^{5}1<=n<=2⋅105 ; 1<=T<=10^{9}1<=T<=109 ) — the number of problems in the exam and the length of the exam in milliseconds, respectively.

Each of the next nn lines contains two integers a_{i}ai​ and t_{i}ti​ ( 1<=a_{i}<=n1<=ai​<=n ; 1<=t_{i}<=10^{4}1<=ti​<=104 ). The problems are numbered from 1 to nn .

输出格式

In the first line, output a single integer ss — your maximum possible final score.

In the second line, output a single integer kk ( 0<=k<=n0<=k<=n ) — the number of problems you should solve.

In the third line, output kk distinct integers p_{1},p_{2},...,p_{k}p1​,p2​,...,pk​ ( 1<=p_{i}<=n1<=pi​<=n ) — the indexes of problems you should solve, in any order.

If there are several optimal sets of problems, you may output any of them.

题意翻译

题目描述 你正在准备一场关于调度理论的考试。这场考试会持续正好T毫秒,由n道题目组成。你可以用t[i]毫秒解决第i个问题,或者忽略它并不消耗时间。你也不需要用来在做完一道题之后休息的时间。 不幸的是,你的老师认为一些题目对你来说太简单了。因此,他对于每道题i规定了一个整数a[i],表示题目i只在你总共解决了不超过a[i]个问题(包括问题i)的情况下为你的最终成绩加上一分。 正式地,假设你在考试中解决了问题p[1],p[2],……,p[k]。那么,你的最终成绩s会等于在1到k之间的满足k<=a[p[j]]的j的个数。 你已经意识到这场考试真正的第一道题目已经放在了你面前。因此,你想要选择一组题目来解决,从而最大化你的最终成绩。不要忘记这场考试有时间限制,而你必须有足够的时间来解决所有你选择的题目。如果存在多个最优解,任意输出一组即可。 输入输出格式 输入格式: 第一行包含2个整数,n和T(1<=n<=200000;1<=T<=1000000000)——分别是考试中题目的数量和考试时长的毫秒数。 接下来的n行每行包括两个整数a[i]和ti。题目编号从1到n。 输出格式: 在第一行,输出一个单独的整数s——你的可能得到的最终成绩的最大值。 在第二行,输出一个单独的整数k(0<=k<=n)——你应该解决的问题数量。 在第三行,以任意顺序输出k个不同整数p[1],p[2],……,pk,即你应当解决的题目编号。 如果有多个最优解,你可以输出其中任意一个。 说明 在第一个样例中,你应该解决题目3、1和4。在这种解下你会花费80+100+90=270毫秒,在考试的长度300ms以内(甚至给自己留出了30ms休息时间)。题目3和题目1会分别为你带来1分,然而题目4不会。你会得到2分。 在第二个样例中,这场灾难性的考试的长度甚至不足以解决一道题目(所以你显然一分都得不到)。 在第三个样例中,你刚好有足够的时间(42+58=100)来解决这两道题并且微笑着把答卷交给老师。 贡献者:fbhou

输入输出样例

输入 #1复制

5 300
3 100
4 150
4 80
2 90
2 300

输出 #1复制

2
3
3 1 4

输入 #2复制

2 100
1 787
2 788

输出 #2复制

0
0

输入 #3复制

2 100
2 42
2 58

输出 #3复制

2
2
1 2

说明/提示

In the first example, you should solve problems 3, 1, and 4. In this case you'll spend 80+100+90=27080+100+90=270 milliseconds, falling within the length of the exam, 300 milliseconds (and even leaving yourself 30 milliseconds to have a rest). Problems 3 and 1 will bring you a point each, while problem 4 won't. You'll score two points.

In the second example, the length of the exam is catastrophically not enough to solve even a single problem.

In the third example, you have just enough time to solve both problems in 42+58=10042+58=100 milliseconds and hand your solutions to the teacher with a smile.


思路:开始想二分然后直接贪了一波wa了。

首先考虑一个事情,如果说要拿k分,那么k个题就够了。假如去拿k+1题,然后只获得了k分,那么说明有一道题的a[i]<=k,这道题直接不要就好了。也就是说拿k+1个题获得k分,那么肯定拿k个题就能获得k分。那道题扔掉多出时间来,也不会让枚举的答案变小。

于是按照时间从小到大排序,当枚举到的mid>a[i]时候,这个题不要。O(n)check一下就好。

当然我wa15wa了好久总是对不上。我觉得有点奇怪quq,二分的check里面存下来的不一定是刚刚好的,在一个跳出while的时候完全可以是多的,但是第15个点是少了1个的。翻了翻当时比赛的代码发现有一部分的情况和我一样..不清楚为啥。

这里就不用每次放check里面收集每个物品的id,二分完后再统一根据k分数和时间有多少来收集id

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+100;
typedef long long LL;
LL n,T,c[maxn],cnt;
struct node{
	LL a;LL t;LL id;
}thing[maxn];
bool cmp(node A,node B){
	if(A.t==B.t) return A.a<B.a;
	return A.t<B.t;
}
bool check(LL x)//枚举做x题 
{
	LL tot=T;LL ans=0;//cnt=0;
//	for(LL i=0;i<=n+10;i++) c[i]=0;
	for(LL i=1;i<=n;i++){
		if(tot<thing[i].t) break;
		if(thing[i].a<x) continue;
		ans++;
		tot-=thing[i].t;
	//	c[++cnt]=thing[i].id;
	}
//	debug(cnt);
	return ans>=x;
}
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  cin>>n>>T;
  for(LL i=1;i<=n;i++){
  	cin>>thing[i].a>>thing[i].t;thing[i].id=i;
  } 
  sort(thing+1,thing+1+n,cmp);
  LL l=0;LL r=n;
  while(l<r)//枚举能做k题获得k分 
  {
  	LL mid=(l+r+1)/2;
  	if(check(mid)) l=mid;
  	else r=mid-1;
  }
  cout<<l<<endl;
  cout<<l<<endl;
//  cout<<cnt<<endl;
//  for(LL i=1;i<=cnt;i++) cout<<c[i]<<" ";
//  cout<<endl;
  LL tmp=T;cnt=0;
  for(LL i=1;i<=n;i++){
  	if(thing[i].a<l) continue;
  	if(tmp<thing[i].t) break;
  	cout<<thing[i].id<<" ";
  	tmp-=thing[i].t;
  	cnt++;
  	if(cnt==l) break;
  }
return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值