Productive Meeting(优先队列)

题目链接:Problem - D - Codeforces

题目大意就是给你一些人以及他们的社交参数,每两个人交流一次,他们的社交参数就会各自减一,当社交参数减少为0时,这个人将无法交流,问社交参数减少的权值和最多为多少。

分析:我一开始想的是对这些人的社交能力进行从大到小排序,然后依次选择社交参数最大和次大的人进行交流,当社交参数次大的人社交参数为0时,再把社交参数最大的那个人的剩余社交参数加回队列,依次重复上述过程,我这样想是有问题的,比如 

有三个人 社交参数分别为 2 2 2,按照我的那种思路,算出来的结果是2,但正确结果应该是1号先与2号交流,再分别用1号和2号与三号交流,这样得到的结果是3。

这个样例就启发我们对原来的想法加以完善,就是每次选取社交参数最大和次大的人进行交流,但是每次只交流一次,使他们的社交参数分别减1,再次将他们加入队列,重新选取社交参数最大和次大的人进行交流,重复上述过程,直至队列中只剩下一个人。下面是代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N=2e5+10;
int l[N],r[N];
struct node{
	int pos,val;
	bool operator<(const node &t)const{
		return t.val>val;
	}
};
priority_queue<node>q;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		while(q.size()) q.pop();
		int n;
		scanf("%d",&n);
		int t;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&t);
			if(t)//如果值不为0就加入队列 
			q.push({i,t});
		}
		int cnt=0;//记录交谈次数 
		long long ans=0;
		while(q.size()>=2)
		{
			node a=q.top();
			q.pop();
			node b=q.top();
			q.pop();
			l[++cnt]=a.pos;
			r[cnt]=b.pos;
			if(a.val>1)
			q.push({a.pos,a.val-1});
			if(b.val>1)
			q.push({b.pos,b.val-1});
		}
		printf("%d\n",cnt);
		for(int i=1;i<=cnt;i++)
			printf("%d %d\n",l[i],r[i]);
	}
	return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值