Loading

[NOI2019] 序列 题解

CF436E Cardboard Box的升级版。

直接上来搞六个堆的反悔贪心。

思路

首先按照贪心的思路,将两个序列中最大 \(k\) 个直接选。

如果其中相同的小于 \(l\) ,我们考虑进行反悔贪心。

我们设当前序列相同的个数为 \(res\)

我们每一回合都要让 \(res+1\)

应该有四种情况:

  1. 选择一个之前选了 \(b\) 没选 \(a\) 的位置,将 \(a\) 选上,再丢掉一个只选了 \(a\) 的位置上的 \(a\)

  2. 选择一个之前选了 \(a\) 没选 \(b\) 的位置,将 \(b\) 选上,再丢掉一个只选了 \(b\) 的位置上的 \(b\)

  3. 选择一个之前选了 \(b\) 没选 \(a\) 的位置,和一个之前选了 \(a\) 没选 \(b\) 的位置,将 \(a,b\) 选上,再丢掉一个选了 \(a,b\) 的位置上的 \(a,b\)

  4. 选择一个什么都没选位置上的 \(a,b\),将他们选上,再选择一个之前选了 \(b\) 没选 \(a\) 的位置,和一个之前选了 \(a\) 没选 \(b\) 的位置,将 \(a,b\) 丢掉。

列成式子就是:

  1. \(a_{max}-a_{min}\)

  2. \(b_{max}-b_{min}\)

  3. \((a+b)_{max}-a_min-b_min\)

  4. \(a_{max}+b_{max}-(a+b)_{min}\)

然后就可以开六个堆来维护这些式子。

最后,就是板子了。

Code

#include <bits/stdc++.h>
using namespace std;

inline int read()
{
    int s = 0 , f = 1; char ch;
    while(!isdigit(ch = getchar())) if(ch == '-') f = -1;
    while(isdigit(ch)) s = s * 10 + ch - '0' , ch = getchar();
    return s * f;
}

const int maxn = 200010;

int t , n , k , l , vis[maxn] , a[maxn] , b[maxn];

struct edge
{
	int id , num;
}al[maxn] , bl[maxn];

inline bool cmp(edge x , edge y)
{
	return x.num > y.num;
}

struct qwq
{
	int sum , id;
	inline bool operator<(const qwq &tmp) const
	{
		return sum < tmp.sum;
	}
	
	inline bool operator>(const qwq &tmp) const
	{
		return sum > tmp.sum;
	}
};

priority_queue<qwq , vector<qwq> , less<qwq> > q1 , q2 , q6;
priority_queue<qwq , vector<qwq> , greater<qwq> > q3 , q4 , q5;

/*
q1 -> a_i          q2 -> b_i
q3 -> a_i          q4 -> b_i
q5 -> a_i + b_i    q6 -> a_i + b_i
*/

inline void solve(int i)
{
	if(vis[i] == 0) q6.push({a[i] + b[i] , i});
	if(vis[i] == 1) q2.push({b[i] , i}) , q3.push({a[i] , i});
	if(vis[i] == 2) q1.push({a[i] , i}) , q4.push({b[i] , i});
	if(vis[i] == 3) q5.push({a[i] + b[i] , i});
}

inline void init()
{
	memset(vis , 0 , sizeof(vis));
	while(q1.empty() == 0) q1.pop();
	while(q2.empty() == 0) q2.pop();
	while(q3.empty() == 0) q3.pop();
	while(q4.empty() == 0) q4.pop();
	while(q5.empty() == 0) q5.pop();
	while(q6.empty() == 0) q6.pop();
}

signed main()
{
	t = read();
	while(t--)
	{
		init();
		long long sum = 0 , res = 0;
		//sum当前和,res当前匹配数量. 
		n = read() , k = read() , l = read();
		for(int i = 1;i <= n;i++) a[i] = read() , al[i] = {i , a[i]};
		for(int i = 1;i <= n;i++) b[i] = read() , bl[i] = {i , b[i]};
		sort(al + 1 , al + n + 1 , cmp);
		sort(bl + 1 , bl + n + 1 , cmp);
		for(int i = 1;i <= k;i++)
			sum += al[i].num , vis[al[i].id] = (vis[al[i].id] > 0 ? 3 : 1),
			sum += bl[i].num , vis[bl[i].id] = (vis[bl[i].id] > 0 ? 3 : 2);
		//vis_i == 1 只选 a_i
		//vis_i == 2 只选 b_i
		//vis_i == 3 都选了. 
		for(int i = 1;i <= n;i++)
			res += (vis[i] == 3);
		for(int i = 1;i <= n;i++) solve(i);
		while(res < l)
		{
			long long lsum = -10000000000 , casel = 0;
			
			while(q1.empty() == 0 && vis[q1.top().id] != 2) q1.pop();
			while(q2.empty() == 0 && vis[q2.top().id] != 1) q2.pop();
			while(q3.empty() == 0 && vis[q3.top().id] != 1) q3.pop();
			while(q4.empty() == 0 && vis[q4.top().id] != 2) q4.pop();
			while(q5.empty() == 0 && vis[q5.top().id] != 3) q5.pop();
			while(q6.empty() == 0 && vis[q6.top().id] != 0) q6.pop();
			
			if(q1.empty() == 0 && q3.empty() == 0)
			{
				if(lsum < q1.top().sum - q3.top().sum)
					lsum = q1.top().sum - q3.top().sum , casel = 1;
			}
			
			if(q2.empty() == 0 && q4.empty() == 0)
			{
				if(lsum < q2.top().sum - q4.top().sum)
					lsum = q2.top().sum - q4.top().sum , casel = 2;
			}
			
			if(q1.empty() == 0 && q2.empty() == 0 && q5.empty() == 0)
			{
				if(lsum < q1.top().sum + q2.top().sum - q5.top().sum)
					lsum = q1.top().sum + q2.top().sum - q5.top().sum , casel = 3;
			}
			
			if(q3.empty() == 0 && q4.empty() == 0 && q6.empty() == 0)
			{
				if(lsum < q6.top().sum - q3.top().sum - q4.top().sum)
					lsum = q6.top().sum - q3.top().sum - q4.top().sum , casel = 4;
			}
			
			if(casel == 1)
				vis[q1.top().id] = 3 , vis[q3.top().id] = 0,
				solve(q1.top().id) , solve(q3.top().id),
				q1.pop() , q3.pop();
				
			if(casel == 2)
				vis[q2.top().id] = 3 , vis[q4.top().id] = 0,
				solve(q2.top().id) , solve(q4.top().id),
				q2.pop() , q4.pop();
				
			if(casel == 3)
				vis[q1.top().id] = 3 , vis[q2.top().id] = 3 , vis[q5.top().id] = 0,
				solve(q1.top().id) , solve(q2.top().id) , solve(q5.top().id),
				q1.pop() , q2.pop() , q5.pop();
				
			if(casel == 4)
				vis[q3.top().id] = 0 , vis[q4.top().id] = 0 , vis[q6.top().id] = 3,
				solve(q3.top().id) , solve(q4.top().id) , solve(q6.top().id),
				q3.pop() , q4.pop() , q6.pop();
			
			sum += lsum , res++;
		}
		cout << sum << endl;
	}
    return 0;
}
posted @ 2022-02-18 09:01  JiaY19  阅读(51)  评论(0编辑  收藏  举报