Examples

CF1599A Weights 解题报告

CF1599A Weights 解题报告:

更好的阅读体验

题意

\(n\) 个数,你要把它们按照任意的顺序放入两个集合 \(L,R\) 中,满足第 \(i\) 次放置数之后集合 \(s_i=\{L,R\}\) 更大,输出任意方案或报告无解。

\(1\leqslant n\leqslant 2\times 10^5,1\leqslant a_i\leqslant 10^9\)

分析

ISIJ T3,hzr 考场就切了,而我在半年后还只会贺题解,实力差距就这么大吗。

不妨令 \(s_n=L\),若不是可以直接交换集合 L,R。

考虑一个很经典的问题,给定的串为 \(LRLRLRL\cdots\) 形式的,容易发现给 \(a\) 排序之后交错放入两个集合中即可满足条件。

容易发现正着构造并不好处理,原因是你不好保存两个集合的差。正难则反,我们考虑不断从两个集合中删除元素。

一个简单而容易被忽略的性质是对于按照大小交错放入两个集合内的数,删去其最小的不会改变集合大小关系,删去其最大的一定会改变集合大小关系。

利用这个性质我们就可以维护当前剩下的区间直接模拟了,时间复杂度 \(O(n\log n)\)

代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200005;
int n,c;
int a[maxn],b[maxn];
string s;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+1+n);
	cin>>s,s=" "+s;
	for(int l=1,r=n,i=n;i>=1;i--){
		if(s[i]!=s[i-1])
			b[i]=r,r--;
		else b[i]=l,l++;
	}
	for(int i=1;i<=n;i++)
		printf("%d %c\n",a[b[i]],((b[i]&1)^(s[n]=='R')^(n&1))==0? 'L':'R');
	return 0;
}
posted @ 2021-10-31 19:55  xiaoziyao  阅读(106)  评论(1编辑  收藏  举报