您的位置:首页 > 其它

Codeforces Round #193 (Div. 2) C. Students' Revenge (两种优先级的贪心 好题)

2013-08-01 23:08 369 查看
C. Students' Revenge

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard output

A student's life is fraught with complications. Some Berland University students know this only too well. Having studied for two years, they contracted strong antipathy towards the chairperson of some department. Indeed, the person in question wasn't the kindest
of ladies to begin with: prone to reforming groups, banning automatic passes and other mean deeds. At last the students decided that she just can't get away with all this anymore...

The students pulled some strings on the higher levels and learned that the next University directors' meeting is going to discuss n orders about the chairperson
and accept exactly p of them. There are two values assigned to each order: ai is
the number of the chairperson's hairs that turn grey if she obeys the order and bi —
the displeasement of the directors if the order isn't obeyed. The students may make the directors pass any p orders chosen by them. The students know that
the chairperson will obey exactly k out of these p orders.
She will pick the orders to obey in the way that minimizes first, the directors' displeasement and second, the number of hairs on her head that turn grey.

The students want to choose p orders in the way that maximizes the number of hairs on the chairperson's head that turn grey. If there are multiple ways to
accept the orders, then the students are keen on maximizing the directors' displeasement with the chairperson's actions. Help them.

Input

The first line contains three integers n (1 ≤ n ≤ 105), p (1 ≤ p ≤ n), k (1 ≤ k ≤ p)
— the number of orders the directors are going to discuss, the number of orders to pass and the number of orders to be obeyed by the chairperson, correspondingly. Each of the followingn lines
contains two integers ai and bi (1 ≤ ai, bi ≤ 109),
describing the corresponding order.

Output

Print in an arbitrary order p distinct integers — the numbers of the orders to accept so
that the students could carry out the revenge. The orders are indexed from 1 to n in the order they occur in the input. If there are multiple solutions,
you can print any of them.

Sample test(s)

input
5 3 2
5 6
5 8
1 3
4 3
4 11


output
3 1 2


input
5 3 3
10 18
18 17
10 20
20 18
20 18


output
2 4 5


Note

In the first sample one of optimal solutions is to pass orders 1, 2, 3. In this case the chairperson obeys orders number 1 and 2. She gets 10 new grey hairs in the head and the directors' displeasement will equal 3. Note that the same result can be achieved
with order 4 instead of order 3.

In the second sample, the chairperson can obey all the orders, so the best strategy for the students is to pick the orders with the maximum sum of ai values.
The chairperson gets 58 new gray hairs and the directors' displeasement will equal 0.

题意和思路来源于男神cms博客

链接:http://blog.csdn.net/cc_again/article/details/9471465

题目意思:

有n个命令,要通过p个,某主席要在通过的p个中选择k个接受。

每个任务有两个值ai,bi, ai表示如果该主席接受该命令,她的头发变灰的数量,bi表示如果该主席不接受该命令时,议员不高兴值。

对于通过的p个命令,该主席要使议员的不高兴值和最小,在相同的情况下,要使自己的头发变灰的数量尽可能的少。

让你求出通过哪p个命令,使得该主席的头发变灰的数量最多,在相同的情况下,输出使议员不高兴最大的选择。
解题思路:

首先须知道,对于每一个选择(p命令),该主席一定是把b值最小的p-k个不接受,如果b有相同的,则尽可能使自己的头发变灰的数量最小即a值尽量大。

step1:按 b:小->大  a:大->小 排序,前p-k个无论a有多大,如果选它都没用,a不能发挥作用,所以只能在后面的n-(p-k)个里选。

step2:按 a: 大->小 b:大->小 排序,选择前k个,使得suma最大,b的最小值也最大(因为要保证主席需要接受它)。

step3:保证了k个命令的suma最大后,剩下的任务就是保证p-k个命令的sumb最大了。再次像step1中那样排序,此时注意在a、b相同时应把已经选在k个中的尽量靠前,然后依次输出后面的命令下标就够了。

主要思想:

当有两个优先级不同的限制条件时,先以第二优先级的最坏的打算来保证第一优先级,再在第一优先级得到满足条件下,来使得第二优先条件(本题是愤怒值最大)得到满足。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100005
using namespace std;

int n,m,p,k,ans;
int vis[maxn];
struct Node
{
int a,b,id;
int state;
}node[maxn];

bool cmp1(const Node&x1,const Node&x2) // 按 b: 小->大 a:大->小 排序
{
if(x1.b!=x2.b) return x1.b<x2.b;
if(x1.a!=x2.a) return x1.a>x2.a;
return x1.state<x2.state; // 最后按state由小到大排序 后面给出解释
}
bool cmp2(const Node&x1,const Node&x2) // 按 a: 大->小 b:大->小 排序
{
if(x1.a!=x2.a) return x1.a>x2.a;
return x1.b>x2.b;
}
int main()
{
int i,j,cnt,num;
while(~scanf("%d%d%d",&n,&p,&k))
{
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
{
scanf("%d%d",&node[i].a,&node[i].b);
node[i].id=i;
node[i].state=0;
}
sort(node+1,node+n+1,cmp1);
for(i=1;i<=p-k;i++)
{
node[i].state=1;
}
sort(node+1,node+n+1,cmp2);
cnt=0;
for(i=1;cnt<k;i++)
{
if(!node[i].state)
{
cnt++;
vis[node[i].id]=1;
node[i].state=2; // 将state的值修改
if(cnt==1) printf("%d",node[i].id);
else printf(" %d",node[i].id);
}
}
sort(node+1,node+n+1,cmp1);
cnt=num=0;
for(i=n;num<p-k;i--) // 从后往前找 此处能解释为什么 state是由小到大排序
/* ps:开始WA在第29组数据了 说我输出了0 我怎么也想不通 debug我好久 ╮(╯▽╰)╭ 后来才发现可能是因为
如果a、b都相同 则要把已经输出了的放在前面 这样cnt才能加到k 才能输出完后面的p-k个下标 否则要输出0了 */
{
if(cnt>=k)
{
num++;
printf(" %d",node[i].id);
}
if(vis[node[i].id]) cnt++;
}
printf("\n");
}
return 0;
}
/*
10 7 4
4 3
5 3
5 5
4 3
4 5
3 5
4 5
4 4
3 5
4 5
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐