hihoCoder#1838 : 鎕鎕鎕 贪心
题解:
神奇的贪心题,,,感觉每次做贪心题都无从下手。。。
我们首先按照a对所有卡片从小到大排序,然后从1开始,从连续的两张牌中取b最大的,最后一张单出来的也取了。
可以证明,这样的方案一定是合法的。
为什么呢?
假设我们将排序后的牌按照(1, 2) (3, 4) ……这样的方式两两分组,那么既然我们每次都是取b最大的那张,b的限制显然我们已经满足了。
现在来考虑a,假设我们遇到了最坏的情况,在每一组里面,我们都取到了a最小的那个,即我们取到了第1, 3, 5,……张牌(因为已经排好序了,所以a最小的一定是这些),那么这个时候我们可以改变一下分组方式由原来的(1, 2) (3, 4) ……变成1, (2, 3), (4, 5) ……(2 * n, 2 * n + 1),那么你可以发现,这时我们取的牌就变成了任意组当中a最大的那张,因此a也是满足条件的。
证明完毕。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 210000 5 6 int n; 7 8 struct card{ 9 int a, b, id; 10 }s[AC]; 11 12 inline bool cmp(card x, card y) 13 { 14 return x.a < y.a; 15 } 16 17 inline int read() 18 { 19 int x = 0;char c = getchar(); 20 while(c > '9' || c < '0') c = getchar(); 21 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 22 return x; 23 } 24 25 void pre() 26 { 27 n = read(); 28 int b = 2 * n + 1; 29 for(R i = 1; i <= b; i ++) 30 s[i].a = read(), s[i].b = read(), s[i].id = i; 31 sort(s + 1, s + b + 1, cmp); 32 } 33 34 void work() 35 { 36 int b = 2 * n; 37 for(R i = 1; i <= b; i += 2) 38 { 39 if(s[i].b > s[i + 1].b) printf("%d\n", s[i].id); 40 else printf("%d\n", s[i + 1].id); 41 } 42 printf("%d\n", s[2 * n + 1].id); 43 } 44 45 int main() 46 { 47 freopen("in.in", "r", stdin); 48 pre(); 49 work(); 50 fclose(stdin); 51 return 0; 52 }