Codeforces B. Too Easy Problems
Posted 小张人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于Codeforces B. Too Easy Problems的主要内容,如果未能解决你的问题,请参考以下文章
CF 1249D1 - Too Many Segments (easy version) 贪心+排序+set的使用
[Codeforces] Too Many Segments
2017博普杯 东北大学邀请赛(B. Drink too much water)(贪心+树链剖分)
Codeforces 71A Way Too Long Words