【做题笔记】CF1659D Reverse Sort Sum

Problem

CF1659D Reverse Sort Sum

题目大意:

有一个长度为 \(n\)\(01\) 序列 \(a\)。定义 \(b_{i,j}\) 为将 \(a\)\(1\)\(j\) 排序后第 \(a_i\) 的值。定义 \(c_i=\sum\limits_{j=1}^n b_{i,j}\)。现在给你序列 \(c\),求一个合法的 \(a\)

Solution

首先 \(c\) 中最前面若干个 \(0\) 的位置显然有 \(a_i=0\)
\(c\) 中第一个非 \(0\) 的位置必然有 \(a_i=1\)

考虑这之后的数。

首先容易发现,对于每个序列 \(b_{i,j}(i \le j)\),一定是前面若干个 \(1\),然后跟若干个 \(0\)

然后我们考虑转化问题,将问题转化成不断添加数字,容易发现第一个 \(b_{i,j}=0(i \le j)\) 的时刻 \(j\) 满足 \(\sum\limits_{k=1}^j [a_i=0] = i\)。所以可以考虑用前面的序列去推后面的部分。

考虑按当前 \(a_i\) 的值分类讨论:

\(a_i=0\) 时,有 \(\forall j \in [i,i+c_i-1],b_{i,j}=1\),以及 \(b_{i,i+c_i}=0\)。故在 \(i+c_i\) 的位置添加进去后有恰好 \(i\)\(0\),故有 \(a_{i+c_i}=0\)

\(a_i=1\) 时,有 \(\forall j \in [1,c_i],b_{i,j}=1\),以及 \(b_{i,c_i+1}=0\)。故在 \(c_+1i\) 的位置添加进去后有恰好 \(i\)\(0\),故有 \(a_{c_i+1}=0\)

对于没有被上面两种扫到的位置,显然可以当做 \(1\) 处理。

Code

//Think twice,code once.
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int T,n,a[200005];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) a[i]=1;
		for(int i=1;i<=n;i++)
		{
			int c;
			scanf("%d",&c);
			if(c==0) a[i]=0;
			if(a[i]==0) a[i+c]=0;
			else a[c+1]=0;
		}
		for(int i=1;i<=n;i++) printf("%d ",a[i]);
		puts("");
	}
	return 0;
}
posted @ 2022-09-08 11:31  Mine_King  阅读(47)  评论(0编辑  收藏  举报