Codeforces Round #570 (Div. 3)G. Candy Box (hard version)

原题出处:http://codeforces.com/contest/1183/problem/G

This problem is a version of problem D from the same contest with some additional constraints and tasks.

There are nn candies in a candy box. The type of the ii-th candy is aiai (1≤ai≤n1≤ai≤n).

You have to prepare a gift using some of these candies with the following restriction: the numbers of candies of each type presented in a gift should be all distinct (i. e. for example, a gift having two candies of type 11 and two candies of type 22 is bad).

It is possible that multiple types of candies are completely absent from the gift. It is also possible that not all candies of some types will be taken to a gift.

You really like some of the candies and don't want to include them into the gift, but you want to eat them yourself instead. For each candy, a number fifi is given, which is equal to 00 if you really want to keep ii-th candy for yourself, or 11 if you don't mind including it into your gift. It is possible that two candies of the same type have different values of fifi.

You want your gift to be as large as possible, but you don't want to include too many of the candies you want to eat into the gift. So, you want to calculate the maximum possible number of candies that can be included into a gift, and among all ways to choose maximum number of candies, you want to maximize the number of candies having fi=1fi=1 in your gift.

You have to answer qq independent queries.

If you are Python programmer, consider using PyPy instead of Python when you submit your code.

Input

The first line of the input contains one integer qq (1≤q≤2⋅1051≤q≤2⋅105) — the number of queries.

The first line of each query contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of candies.

Then nn lines follow, each containing two integers aiai and fifi (1≤ai≤n1≤ai≤n, 0≤fi≤10≤fi≤1), where aiai is the type of the ii-th candy, and fifidenotes whether you want to keep the ii-th candy for yourself (00 if you want to keep it, 11 if you don't mind giving it away).

It is guaranteed that the sum of nn over all queries does not exceed 2⋅1052⋅105.

Output

For each query print two integers:

  • the maximum number of candies in a gift you can compose, according to the constraints in the statement;
  • the maximum number of candies having fi=1fi=1 in a gift you can compose that contains the maximum possible number of candies.

Example

input

Copy

3
8
1 0
4 1
2 0
4 1
5 1
6 1
3 0
2 0
4
1 1
1 1
2 1
2 1
9
2 0
2 0
4 1
4 1
4 1
7 0
7 1
7 0
7 1

output

Copy

3 3
3 3
9 5

Note

In the first query, you can include two candies of type 44 and one candy of type 55. All of them have fi=1fi=1 and you don't mind giving them away as part of the gift.

    我们考虑D题的思路:将所有的cntcnt排序,然后从大到小贪心选取。
放到这道题上,为了选出来最优答案,我们还是需要将所有cntcnt排序后进行一次贪心,但是我们很
快发现这样做并不能得到最大的fi=1 的数量。
    怎么办呢?容易发现答案可以拆成若干个互不相同的数相加(就是贪心的过程中每一个种类的糖果
选取的数量),那么我们可以想到,对于一个数xx,能够凑出xx这么多糖果的一定是数量大于等于xx的
糖果种类(这不是废话吗)。接下来我们的问题就是对每一个x选择一个糖果种类xi使得最后
min(x,cnt1[xi])最大所以对于一个数x,我们把所有cnt≥x的都丢到一个集合中,然后选取集合中选取
cnt1最大的那个糖果种类加入答案中。

这样做一定是最优的,证明如下:

考虑最优答案,我们发现如果最优答案下x选择的不是cnt1
不是最大的,那么检查当前cnt1 最大的是否被选择,如果没有被选择,我们一定可以让x改选最大的,
答案至少不会变劣。

如果cnt1  最大的已经被选择了,我们考虑选择cnt1
 的那个数y与x的大小关系。如果y<x,那么就将x,y选择的进行交换,否则不会违反我们从大到小贪心
的规则。
最后我们需要实现一个数据结构,支持插入和查询最大值,用一个堆就可以了。
时间复杂度O(n\log n)O(nlogn)。
#include<bits/stdc++.h>
 
using namespace std;
 
const int maxm = 2e5 + 10;
int cnt0[maxm],cnt1[maxm],a[maxm];
priority_queue<int> q;
 
bool cmp(int a,int b)
{
	return cnt0[a] + cnt1[a] > cnt0[b] + cnt1[b];
}
 
int main()
{
	int t;
	scanf("%d",&t);
	while (t--)
	{
		while (!q.empty()) q.pop();
		int n,x,y;
		scanf("%d",&n);
		for (int i=1;i<=n;i++)
		{
			scanf("%d %d",&x,&y);
			if (y==0) cnt0[x]++;
			else cnt1[x]++;
			a[i] = i;
		}
		sort(a+1,a+n+1,cmp);
		int ans = 0,num = 0,now = 1;
		for (int i=n;i>=1;i--)
		{
			while (cnt0[a[now]]+cnt1[a[now]]>=i)
			{
				q.push(cnt1[a[now]]);
				now++;
			}
			if (q.empty())
				continue;
			int dd = q.top();
			q.pop();
			ans += i;
			num += min(i,dd);
		}
		printf("%d %d\n",ans,num);
		for(int i=1;i<=n;i++)cnt0[i]=cnt1[i]=0;
	}
	return 0;
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值