UVA11136Hoaxorwhat-创新互联

知识点:堆

专业从事企业网站建设和网站设计服务,包括网站建设、域名注册雅安服务器托管、企业邮箱、微信公众号开发、微信支付宝成都小程序开发成都App制作、软件开发、等服务。公司始终通过不懈的努力和以更高的目标来要求自己,在不断完善自身管理模式和提高技术研发能力的同时,大力倡导推行新经济品牌战略,促进互联网事业的发展。

这个题的题意比较好理解,但是比较容易写错,至少我是这么感觉的,看到题,可以很自然的想到用两个堆,一个大根堆一个小根堆来维护数据,但是这个不是对顶堆,然后每一天的最后,我们从分别拿出来一个数,统计答案就行了,题目保证每天的最后都至少有两张,这个想法很自然,但是这个样子是可能出错的,想象一下,假如实际剩余的消费券已经不多了,但是你用完的消费券已经很多了,然后来了一张很小的消费券,那么它进入大根堆的话就会被放的很靠后,前面有很多实际已经用完的但是还没有被你出堆的消费券,然后那些消费券都像是被向前推了一下似的,就有可能会有一个实际已经被用过的再被使用,这样就错了,出错的地方就在于有些用完的消费券不能留着了,又看了看数据,每个消费券的数据范围正好可以来散列,那么就是这个样子了,我们开一数组来散列记录每种消费券的数目,每天结束的时候,循环遍历,数目为零的券都直接删除,直到找到第一个数目不为零的券,用来统计答案,两个堆都是这个样子,这样就不会出错了,

这个题用堆写容易出错的地方就是没有及时删除堆里面实际数量已经是0的消费券,所以每次从堆里面找消费券的时候都要找第一个数量不为0的消费券,并且前面的都要删除

还是感慨一下,一开始看见这个题就有点轻敌了,以为很简单,最后是看了别人的题解才过的,希望自己以后不要这么轻敌了

本题还有更简单的multiset的写法,就不写了

#includeusing namespace std;

const int N = 1e6 + 5;

int h[N];

int main() {
	int n;
	while (cin >>n && n) {
		memset(h, 0, sizeof(h));
		priority_queueq1;
		priority_queue, greater>q2;
		long long ans = 0;
		while (n--) {
			int k;
			scanf("%d", &k);
			while (k--) {
				int x;
				scanf("%d", &x);
				q1.push(x); q2.push(x);
				h[x]++;
			}
			while (!h[q1.top()]) q1.pop();
			while (!h[q2.top()]) q2.pop();
			ans += (long long) q1.top() - q2.top();
			h[q1.top()]--; h[q2.top()]--;
		}
		cout<< ans<< '\n';
	}
	return 0;
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:UVA11136Hoaxorwhat-创新互联
文章地址:http://ybzwz.com/article/dgppgp.html