Codeforces B. Too Easy Problems

题目描述:

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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 jbetween 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·105; 1 ≤ T ≤ 109) — 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 ai and ti (1 ≤ ai ≤ n; 1 ≤ ti ≤ 104). 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 p1, p2, ..., pk (1 ≤ 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.

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.

思路:

刚开始:音乐觉得应该用贪心,但具体怎么做不清楚,只是单纯的用qsort把结构体数组先按a这个属性从小到大排序,若a相同,将时间按从大到小排序

样例1排序结果如下:

2    2  3    4  4

300  90  100  150  80

然后怎么贪心呢?先是胡思乱想,想的是从后往前,只要时间够,就加到答案里,时间不够就跳过该数,可显然不对,过了十几个样例(惊了)后终于卡住。问题出在哪?发现这个算法就是只要时间够就往上加,导致与题目的要求完全不符。那题目的意思是?

是在总时间的限制条件下,从数组中找有效元素,有效元素越多越好。有效元素就是最后找到的元素个数k要小于等于该元素的a属性值。k越大,导致对有效元素的要求越高(a要越大),最后的平衡点就是最值点。

依照上面刚开始的思路,平衡点之后可以看到在增加元素的个数是没有意义的,因为a值不会增加(已排好序)

那么该怎么做?

此处用到优先队列,类似于上面排好序的结构体数组,不过更为方便,因为是基于堆的实现。再利用二维向量,在读入数据时将a值相同的元素(ind,time)存到二维向量的一个向量中。因为题目要求分数(score)最大,i从n开始枚举,一直减少到0.

对于每个i值,代表想办法把当前情况下的分数弄到i上。将vector中的ai==i的哪一列全部加入优先队列中,再判断,如果元素多了,代表不考虑总是见的情况下,把分数弄到i是可能的。就pop出用时最大的元素,直到数量上得以满足i个有效元素;如果元素不够,说明凑不出分数为i的情况。接着判断队列中元素个数是否为i且总时间满足限制。若满足,那么分数为i的情况凑出来啦,跳出循环,可以输出答案。如果不满足,i--,看下一轮凑不凑得出分数为i的情况,直到答案或0.

知识点:priority_queue

1 struct node
2 {
3     int x,y;
4     bool operator < (const node & a) const
5     {
6         return x<a.x;
7     }
8 };
9 priority_queue <node> q;
priority_queue <int,vector<int>,less<int> > p;priority_queue <int,vector<int>,greater<int> > q;

代码:

 1 #include <iostream>
 2 #include <vector>
 3 #include <queue>
 4 #define max_n 200005
 5 using namespace std;
 6 vector<pair<int,int> > vec[max_n];
 7 struct node
 8 {
 9     int id;
10     int time;
11     friend bool operator<(node a,node b)
12     {
13         return a.time<b.time;
14     }
15 };
16
17 priority_queue<node> que;
18 int n;
19 int T;
20 int main()
21 {
22     cin >> n >> T;
23     for(int i = 0;i<n;i++)
24     {
25         int num,time;
26         cin >> num >> time;
27         vec[num].push_back(pair<int,int>(time,i));
28     }
29     int sum = 0;
30     int score = 0;
31     for(int i = n;i>=0;i--)
32     {
33         for(int j = 0;j<vec[i].size();j++)
34         {
35             node p;
36             p.id = vec[i][j].second+1;
37             p.time = vec[i][j].first;
38             que.push(p);
39             sum += p.time;
40         }
41         while(que.size()>i)
42         {
43             int t= que.top().time;
44             que.pop();
45             sum -= t;
46         }
47         score = i;
48         if(que.size()==i&&sum<=T)
49         {
50             break;
51         }
52     }
53
54     cout << que.size() << endl;
55     cout << score << endl;
56     while(que.size())
57     {
58         cout << que.top().id << " ";
59         que.pop();
60     }
61     return 0;
62 }

原文地址:https://www.cnblogs.com/zhanhonhao/p/11216310.html

时间: 2024-11-03 07:31:49

Codeforces B. Too Easy Problems的相关文章

【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT

[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模924844033.n<=2*10^5. [算法]排列组合+NTT [题解]考虑每个点只会在k个点都在其一个子树时无贡献,即: $$ANS_k=\sum_{x=1}^{n}\binom{n}{k}-\sum_{y}\binom{sz[y]}{k}+\binom{n-sz[y]}{k}$$ 令$cnt_i$表示满足s

【题解】AT2064 Many Easy Problems(转换+NTT)

[题解]AT2064 Many Easy Problems(转换+NTT) 给定一棵树,请你回答\(k\in[1,n]\)由\(k\)个点生成出来的虚树(steiner)的所有方案的大小的和. 对于这种分元素然后每个元素对答案有一个相同的贡献的计数,一般都是考虑对于一个点考虑对于答案的贡献.对于一个确定的\(k\)和一个点\(p\),可以很轻易的算出\(p\)对于答案的贡献=\({n\choose k }-( \sum_{u \in Son}siz[u])-(n-siz[p])\).我们拿个同记

【Codeforces 1096D】Easy Problem

[链接] 我是链接,点我呀:) [题意] 让你将一个字符串删掉一些字符. 使得字符串中不包含子序列"hard" 删掉每个字符的代价已知为ai 让你求出代价最小的方法. [题解] 设dp[i][j]表示前i个字符,已经和"hard"匹配前j个的最小花费. 对于dp[i][j] 对s[i+1]分类讨论 ①s[i+1]不删 那么有两种情况 第一种:s[i+1]和"hard"的第j+1个字符匹配 第二种:..xxxxx不匹配 则分别转移到dp[i+1][

@codeforces - [email&#160;protected] Big Problems for Organizers

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] n 个点连成一棵树,经过每条边需要花费 1 个单位时间. 现给出 m 次询问,每次询问给出两个点,需要求所有点同时出发,最终所有点到达这两个点之一的最小花费时间. input 第一行包含一个整数 n (2?≤?n?≤?100000) ,表示点数. 接下来 n-1 行每行两个 1~n 的

[题解] [AGC005F] Many Easy Problems

题面 题解 学长讲课题目的质量果然和我平常找的那些不一样 思路还是可以说比较巧妙的 考虑到我们并不好算出对于所有大小为 \(i\) 的点集,能够包含它的最小连通块大小 转换题目 这个时候我们应该想到把目标放到单个点 \(i\) 对选择 \(k\) 个点时的贡献 那么他的贡献就是总方案数减去没选的方案数对吧 没选的方案怎么算呢 记 \(sz[i]\) 为以 \(i\) 为根的子树的点数 分析发现, 当 \(k\) 个点同时在以它的儿子为根的一棵子树内就不会计算 \(i\) 这里的儿子的意义是, 以

AGC005F - Many Easy Problems

题目描述 给定一棵树,设 $f_k$ 表示任选 $k$ 个点组成的最小连通块之和,求 $f(i),i \in [1,n]$ 数据范围 $n \le 2 \times 10^5$ 题解 考虑容斥,即一个点对于 $k$ 不会产生贡献的方案数 于是对于一个点 $u$ ,设其为根,它对 $k$ 的贡献可以列出式子: $(_k^n)-\sum_{v \in son_u}(_k^{size_v})$ 于是 $f_k=n(_k^n)-\sum_{i=1}^ng_i(_k^{i})$ ,其中 $g_i$ 表示子

[AGC005]:F - Many Easy Problem

F - Many Easy Problems Time limit : 5sec / Memory limit : 512MB Score : 1900 points Problem Statement One day, Takahashi was given the following problem from Aoki: You are given a tree with N vertices and an integer K. The vertices are numbered 1 thr

Codeforces Hello 2018

A. Modular Exponentiation $2^n$很大的时候直接输出$m$, 不然就把$2^n$算出来. B. Christmas Spruce 没什么可说的. C. Party Lemonade 感觉有点厉害.如果$2c_{i-1}<c_i$ ,那么咱与其买$i$,不如买两个$i-1$.这样循环一遍,更新所有的$c_i$. 然后在从$0$到$31$循环,相当于枚举$l$的二进制位.如果二进制位为$1$就买,如果之前买的能用当前的替换,就把$ans$重新赋值为$c_i$. 1 #in

3.29 练习赛

//比赛时的代码感觉写得真心难看......Orz,还有一堆低级错误贴出来晒晒吧 Problem A     CodeForces 329A     Purification 2A 1 #include "bits/stdc++.h" 2 using namespace std; 3 char mat[110][110]; 4 int n; 5 int row_Col[110], col_Row[110]; 6 7 bool dir_row() 8 { 9 int i, j; 10 b