codeforces 913 D. Too Easy Problems

Description

You are preparing for an exam on scheduling theory. The exam will last for exactly T milliseconds and will consist of n problems. You can either solve problem i in exactly 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 ai to every problem i meaning that the problem i can bring you a point to the final score only in case you have solved no more than ai problems overall (including problem i).

Formally, suppose you solve problems p1, p2, …, pk during the exam. Then, your final score s will be equal to the number of values of j between 1 and k such that 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.

Input

The first line contains two integers n and T (1 ≤ n ≤ 2·10 5 ; 1 ≤ T ≤ 10 9 ) — the number of problems in the exam and the length of the exam in milliseconds, respectively.

Each of the next n lines contains two integers a i and t i (1 ≤ a i  ≤ n; 1 ≤ t i  ≤ 10 4 ). The problems are numbered from 1 to n.

Output

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

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

In the third line, output k distinct integers p 1 , p 2 , …, p k (1 ≤ p i  ≤ 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.

Examples

Input
5 300
3 100
4 150
4 80
2 90
2 300
Output
2
3
3 1 4

Input
2 100
1 787
2 788
Output
0
0

Input
2 100
2 42
2 58
Output
2
2
1 2

Note

In the first example, you should solve problems 3, 1, and 4. In this case you’ll spend 80 + 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 = 100 milliseconds and hand your solutions to the teacher with a smile.


tourist的题解在这里http://codeforces.com/blog/entry/56992

题意:n个任务有两个指标 ai :完成的任务总数超过 ai 时该任务不计分, ti :完成该任务需要的时间,求给定时间T内,最多得几分。
分析:从0到n逐渐增加题目数的方向来分析似乎很困难,不如分析一下问题的解的情况:如果得分为K,那么一定要做K道 ai >=K的题目,而 ai < K的题目做了也不会得分而且会浪费时间,所以最好的答案就是不少于K个 ai ≥ K的题目,并且 ti ≤T,为了让 ti 的和最小,应选取能得分的题目中 ti 最小的K个来做。
思路:二分查找K,以K生成一个最优的答案,如果最优的答案是存在的,那么K是可行的,可以往更大的方向寻找,如果不行,就往更小的方向寻找。在本题中,显然当K满足时,K-1也满足(少做一道题就行了),所以二分是可以的。

PS:研究了tourist的代码学会了很多东西,比如vector的初始化和resize可以节约时间,以前觉得vector会很慢,其实当算法优化到O(n × log(n))时候,vector带来的系数完全是可以接受的,只要在要用到它的地方考虑好大小利用初始化和resize节约时间,vector就能节省很多代码量

#include<stdio.h>
#include<algorithm>
using std::sort;
#include <vector>
using std::vector;
using std::pair;
//#define N_max 200005
int n,T;
typedef vector<int> vect;
typedef vector<pair<int, int>> vecp;

int main() {
    scanf("%d %d", &n,&T);
    vect c(n), t(n),res;
    for (int i = 0; i < n; ++i) {
        scanf("%d %d", &c[i], &t[i]);
    }
    int l = 0, r = n+1, mid = (l + r) / 2;
    int sum,flag;
    vecp a;
    while (l+1<r)
    {
        mid = (l + r) / 2;
        //check mid
        sum = 0; flag = 0;
        a.clear();
        for (int i = 0; i < n; ++i) {
            if (c[i] >= mid) {
                a.emplace_back(t[i],i);
            }
        }
        if (a.size() >= mid) {
            sort(a.begin(), a.end());
            //choose the first ti
            sum = 0;
            for (int t = 0; t < mid; ++t) {
                sum += a[t].first;
            }
            if (sum <= T) {
                flag = 1;
            }
            else {
                flag = 0;
            }
        }
        else {
            flag = 0;
        }
        //mid is ok
        if(flag){
            l = mid;
            res.resize(l);
            for (int p = 0; p < l; ++p) {
                res[p] = a[p].second;
            }
        }
        else {
            r = mid;
        }
    }
    printf("%d\n", l);
    printf("%d\n", res.size());
    for (int t = 0; t < res.size(); ++t) {
        printf("%d%c", res[t]+1, t == res.size() - 1 ? '\n' : ' ');
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值