Loading

Codeforces Global Round 14 D. Phoenix and Socks(贪心/好题)

To satisfy his love of matching socks, Phoenix has brought his n socks (n is even) to the sock store. Each of his socks has a color ci and is either a left sock or right sock.

Phoenix can pay one dollar to the sock store to either:

  • recolor a sock to any color c′ (1≤c′≤n)
  • turn a left sock into a right sock
  • turn a right sock into a left sock

The sock store may perform each of these changes any number of times. Note that the color of a left sock doesn't change when it turns into a right sock, and vice versa.

A matching pair of socks is a left and right sock with the same color. What is the minimum cost for Phoenix to make n/2 matching pairs? Each sock must be included in exactly one matching pair.

Input

The input consists of multiple test cases. The first line contains an integer t (1≤t≤1000) — the number of test cases.

The first line of each test case contains three integers n, l, and r (2≤n≤2⋅10^5; n is even; 0≤l,r≤n;l+r=n) — the total number of socks, and the number of left and right socks, respectively.

The next line contains 𝑛n integers ci (1≤ci≤n) — the colors of the socks. The first l socks are left socks, while the next r socks are right socks.

It is guaranteed that the sum of n across all the test cases will not exceed 2⋅10^5.

Output

For each test case, print one integer — the minimum cost for Phoenix to make n/2 matching pairs. Each sock must be included in exactly one matching pair.

Example

input

Copy

4
6 3 3
1 2 3 2 2 2
6 2 4
1 1 2 2 2 2
6 5 1
6 5 4 3 2 1
4 0 4
4 4 4 3

output

Copy

2
3
5
3

不妨设l大于等于r。首先可以将l和r中颜色相同的凑成一对直接抵消掉,则剩下的l的颜色与r的颜色互不相同(但l中可能有多只同一个颜色的袜子,r同理)。然后考虑怎么给这些配对。如果l和r不相等,设d = l - r,容易知道d是偶数,则肯定有d / 2只左袜子要变成右袜子。一种可行的贪心策略是从l中找两只同样颜色的袜子,将其中一只变成右袜子(当然变完后也要消掉),这样不断处理,当d变为0或者没有两只及以上相同颜色的左袜子。此时若d不为0,则只能将l中的d只左袜子既变方向又变颜色(因为右袜子中和这些相同的颜色的袜子肯定在一开始就被消掉了),对答案贡献为2 * d。这时候l = r,剩下的左袜子右袜子数量相同颜色彼此不同,对答案的贡献为剩下的左/右袜子的数量。

//注意:代码模板中的代码将会被复制到任何新创建的文件中,编辑代码模板中的代码,让他帮你自动增加固定代码吧
#include <iostream> 
#include <vector>
#include <cstring>
using namespace std;
int n, l, r, a[200005], a1[200005],b[200005],b1[200005];
int main(){
    int t;
    cin >> t;
    while(t--) {
        cin >> n >> l >> r;
        for(int i = 1; i <= n; i++) a1[i] = b1[i] = 0;
        for(int i = 1; i <= l; i++) {
            cin >> a[i];
            a1[a[i]]++;//用桶计数
        }
        for(int i = 1; i <= r; i++) {
            cin >> b[i];
            b1[b[i]]++;
        }
        for(int i = 1; i <= n; i++) {
            int tmp = min(a1[i], b1[i]);
            a1[i] -= tmp;//抵销
            b1[i] -= tmp;
        }
        int ans = 0;
        if(l >= r) {
            int d = l - r;
            d /= 2;
             for(int i = 1; i <= n; i++) {
                 while(a1[i] >= 2 && d) {//贪心
                     a1[i] -= 2;
                     d--;
                     ans++;
                 }
                 while(a1[i] && b1[i]) {
                     a1[i]--;
                     b1[i]--;
                 }
             }
             if(d) ans += d * 2;
             for(int i = 1; i <= n; i++) {
                 ans += b1[i];//因为上一步的操作没有在a1体现,此时a1和b1中的和不一样,必须以b1为准
             }
        } else {
            int d = r - l;
            d /= 2;
             for(int i = 1; i <= n; i++) {
                 while(b1[i] >= 2 && d) {
                     b1[i] -= 2;
                     d--;
                     ans++;
                 }
                 while(a1[i] && b1[i]) {
                     a1[i]--;
                     b1[i]--;
                 }
             }
             if(d) ans += d * 2;
             for(int i = 1; i <= n; i++) ans += a1[i];
        }
        cout << ans << endl;
    }
}

posted @ 2021-05-03 20:44  脂环  阅读(161)  评论(0编辑  收藏  举报