将我隐藏,成为星空中崭新的孤岛|

cc0000

园龄:5年1个月粉丝:14关注:5

12.2小记

一套 ABC 能卡一天,我好菜喵。

我是垃圾喵。

link

然后写了一道反悔贪心的题。

[NOI2019] 序列

经典:

这不是普及组套路吗

先贪心的对于两个序列都把最大的 K 个选出来,然后每次都让交集大小增加 1

按照反悔贪心的套路,我们分四种情况讨论。

  1. 选一个 b 选了的,a 没选的下标 x ,选一个 a 选了的, b 没选的下标 y 。贡献为 axay。就是将 a 里选一个 x,并且把 ya 里丢掉
  2. 选一个 a 选了的,b 没选的下标 x ,选一个 b 选了的,a 没选的下标 y。贡献为 axay
  3. 选一个 ab 不选的 xba 不选的 y,两个都没选的 z ,把 x,y 丢掉,然后两个都选 z ,贡献为 az+bzaxby
  4. 选一个 ab 不选的 xba 不选的 y,两个都选的 z ,把 z 都丢掉,然后 bxay

然后就是按照套路,开 6 个堆,维护上面说的那些信息,然后就没了。

其实想通了不是很难喵。

#include <bits/stdc++.h>
using namespace std;
int n;
typedef long long ll;
const int maxn=200030;
int a[maxn],b[maxn],idx1[maxn],idx2[maxn];bool typ1[maxn],typ2[maxn];int op[maxn];
struct node
{
	int val,idx;
	bool operator<(const node &x)const{
		return val<x.val;
	}
};
priority_queue<node> Q1,Q2,Q3,Q4,Q5,Q6;
void add(int i)
{
	if(op[i]==1) Q6.push((node){-(a[i]+b[i]),i});
	if(op[i]==2) Q2.push((node){-a[i],i}),Q3.push((node){b[i],i});
	if(op[i]==3) Q1.push((node){a[i],i}),Q4.push((node){-b[i],i});
	if(op[i]==4) Q5.push((node){a[i]+b[i],i});
}
bool cmp1(int x,int y){return a[x]>a[y];}
bool cmp2(int x,int y){return b[x]>b[y];}
int main()
{
//	freopen("p.in","r",stdin);
	int TT; scanf("%d",&TT);
	while(TT--)
	{
		memset(typ1,0,sizeof(typ1));memset(typ2,0,sizeof(typ2));
		while(Q1.size()) Q1.pop();while(Q2.size()) Q2.pop();while(Q3.size()) Q3.pop();
		while(Q4.size()) Q4.pop();while(Q5.size()) Q5.pop();while(Q6.size()) Q6.pop();
		int n,K,L;scanf("%d%d%d",&n,&K,&L);
		ll ans=0;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]),idx1[i]=i;
		for(int i=1;i<=n;i++)
			scanf("%d",&b[i]),idx2[i]=i;
		sort(idx1+1,idx1+1+n,cmp1); sort(idx2+1,idx2+1+n,cmp2);
		for(int i=1;i<=K;i++)
			typ1[idx1[i]]=typ2[idx2[i]]=1,ans+=a[idx1[i]],ans+=b[idx2[i]];
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(typ1[i]&&typ2[i]) op[i]=1,cnt++,Q6.push((node){-(a[i]+b[i]),i});
			if(typ1[i]&&!typ2[i]) op[i]=2,Q2.push((node){-a[i],i}),Q3.push((node){b[i],i});
			if(!typ1[i]&&typ2[i]) op[i]=3,Q1.push((node){a[i],i}),Q4.push((node){-b[i],i});
			if(!typ1[i]&&!typ2[i]) op[i]=4,Q5.push((node){a[i]+b[i],i});
		}
		for(int i=1;i<=L-cnt;i++)
		{
			while(Q1.size()&&op[Q1.top().idx]!=3) Q1.pop();
			while(Q2.size()&&op[Q2.top().idx]!=2) Q2.pop();
			while(Q3.size()&&op[Q3.top().idx]!=2) Q3.pop();
			while(Q4.size()&&op[Q4.top().idx]!=3) Q4.pop();
			while(Q5.size()&&op[Q5.top().idx]!=4) Q5.pop();
			while(Q6.size()&&op[Q6.top().idx]!=1) Q6.pop();
			ll x1=Q1.size()?Q1.top().val:-1e15;ll x2=Q2.size()?(-Q2.top().val):1e15;
			ll x3=Q3.size()?Q3.top().val:-1e15;ll x4=Q4.size()?(-Q4.top().val):1e15;
			ll x5=Q5.size()?Q5.top().val:-1e15;ll x6=Q6.size()?(-Q6.top().val):1e15;
			ll ans1=x1-x2; ll ans2=x3-x4; ll ans3=x5-x2-x4; ll ans4=x1+x3-x6;
			ll mx=max({ans1,ans2,ans3,ans4});
			ans+=mx;
			if(ans1==mx)
			{
				int x=Q1.top().idx; int y=Q2.top().idx;
				op[x]=1; op[y]=4;add(x); add(y); 
			}
			else if(ans2==mx)
			{
				int x=Q3.top().idx; int y=Q4.top().idx;
				op[x]=1; op[y]=4; add(x); add(y);
			}
			else if(ans3==mx)
			{
				int x=Q2.top().idx; int y=Q4.top().idx; int z=Q5.top().idx;
				op[x]=4,op[y]=4; op[z]=1;
				add(x);add(y);add(z);
			}
			else
			{
				int x=Q1.top().idx; int y=Q3.top().idx; int z=Q6.top().idx;
				op[x]=1,op[y]=1,op[z]=4;
				add(x); add(y); add(z);
			}
		}
		printf("%lld\n",ans);
	}

}

废话

每天就是接受红太阳的光辉照耀。

以下全是危险言论

那个神秘的势能函数我不知道会咕咕咕到神秘时候。

喵。

本文作者:cc0000

本文链接:https://www.cnblogs.com/cc0000/p/16945856.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   cc0000  阅读(20)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起