Codeforces Round #813 (Div. 2)

这一场打得很稀烂QwQ。

开局先看A,开始秒想了一个假掉的做法,WA了3发,以后一定要先证明正确性再写。。。

A写了16分钟。。。

B很快在35分钟的时候秒掉了,C想到了一个暴力做法,但是由于太暴力了,TLE了一发,稍微优化了一下就过掉了(1h19分)。

之后一个小时在推 E 的式子,但一直陷在死循环里,找不到突破口,浅看一下D,感觉好像要写线段树维护区间然后贪心之类的,没有细想,继续推 E 式子到结束。

A Wonderful Permutation

题意

给出一个长为 \(n\) 的排列 \(p\),每一次操作可以交换任意两个位置的数,求使得 \(p_1 + p_2 \cdots p_k\) 最小所需的最小操作次数。

思路

由于 \(p\) 是一个排列,所以使得只要使得 $$\max_{i=1}^{k} a_i \le k$$ 即可。

所以我们判断一下从 \(a_1\)\(a_k\) 中是否有大于 \(k\) 的数,是就输出 No,否则输出 Yes

注意多组数据。

const int N = 105;
int a[N];
int n, k;
void solve()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	
	int ans = 0; 
	for(int i=1;i<=k;i++) 
	{
		if(a[i] > k) ans ++;
	}
	
	cout<<ans<<endl;
}

B Woeful Permutation

题意

求一个长度为 \(n\) 的排列 \(a\),使得 \(\operatorname{lcm}(1,a_1)+\operatorname{lcm}(2,a_2)+\cdots+\operatorname{lcm}(n,a_n)\) 最大。

思路

对于 \(n\) 为奇数的情况,最后答案为 \(1,3,2,5,4,7,6 \cdots,n,n-1\)

对于 \(n\) 为奇数的情况,最后答案为 \(2,1,4,3,6,5 \cdots ,n, n-1\)

Proof

由于 \(\operatorname{lcm}(x,y) = \frac{x \times y}{\gcd(x,y)}\),所以当 \(x,y\) 互质的时候最优。

我们发现,一个数和最小(或大)的比它大(或者小)的且与它互质的数求 \(\operatorname{lcm}\) 时,是最优的。

那为什么不去和更大的且与它互质的数求 \(lcm\) 呢?

设原来的配对为 \(\frac{x_1 \times y_1}{1} + \frac{x_2 \times y_2}{1} (x_1 \le y_1 \le x_2 \le y_2)\),交换成\(\frac{x_1 \times y_2}{1} + \frac{x_2 \times y_1}{1}\),的话会导致答案偏小。

const int N = 1e5 + 10;
int a[N];
void solve()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) a[i] = i;
	if(n % 2 == 1) for(int i=2;i<n;i+=2) swap(a[i],a[i+1]);
	if(n % 2 == 0) for(int i=1;i<=n;i+=2) swap(a[i],a[i+1]);
	
	for(int i=1;i<=n;i++) cout<<a[i]<<' ';
	cout<<endl;
}

C Sort Zero

题意

给出一个长为 \(n\) 的序列 \(a\),每一次操作可以选择一个数 \(x\),将 \(a\) 中的所有等于 \(x\) 的数变为 \(0\),求将序列变成不下降序列所需要的最少操作次数。

思路

我们发现,一旦出现了 \(a_i > a_{i+1}\),那么我们就要将下标为 \(1 \sim i\) 的数都变成 \(0\)

Proof:

如果只是将 \(a_i\) 变为 \(0\),由于原序列中所有数都是大于 \(0\) 的,所以如果 \(a_{i-1} \ne 0\),就有 \(a_{i-1} > a_i\)

如此类推, 下标为 \(1 \sim i\) 的数都一定为 \(0\)

所以我们只要用 set 维护 \(1 \sim i\) 值的个数,如果出现 \(a_i > a_{i+1}\),就将 \(1 \sim i\) 中的所有值标记为 \(0\),答案更新为 \(1 \sim i\) 中值的个数即可。

const int N = 1e5 + 10;

int n;
int a[N];
bool st[N];

int main()
{
	int t = 1;
	cin>>t;

	while(t--) 
	{
		scanf("%d",&n);
		for(int i=0;i<=n;i++) st[i] = 0;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		
		int ans = 0, last = 0;
		set<int> S;
		for(int i=1;i<n;i++)
		{
			if(st[a[i]]) a[i] = 0;
			if(st[a[i+1]]) a[i+1] = 0;
			if(a[i] != 0) S.insert(a[i]);
			
			if(a[i] > a[i+1])
			{
				for(int j=last;j<=i;j++) st[a[j]] = 1;
				last = i;
				ans = S.size();
			}
		}
		
		cout<<ans<<endl;
	}

    return 0;
}
posted @ 2022-08-14 01:50  BorisDimitri  阅读(74)  评论(0编辑  收藏  举报