【Codeforces】Codeforces Global Round 23 赛中过题记录 A-C

137 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 1 月更文挑战」的第17天,点击查看活动详情

【Codeforces】Codeforces Global Round 23 A-C

题目链接

Dashboard - Codeforces Global Round 23 - Codeforces

A Maxmina

题目大意

给定一个长度为 nn 的数字串,仅包括 0 和 1。有以下两种操作:

  1. kk 个数变为他们的最大值(k个数变成1个数)
  2. 将相邻的两个数变为他们的最小值(2个数变成1个数)

询问是否可以将这个数字串变成仅含有一个数字且为 1 的串。

思路

已知如果数字串中含有数字 1,答案为 YES,否则输出 NO。

代码

#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int solve()
{
	scanf("%d",&n);
	scanf("%d",&m);
	int x,flag=0;
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&x);
		if (x==1) flag=1;
	}
	return flag;
//	scanf("%d",&k);
}
int main()
{
	int T=1;
	for (scanf("%d",&T);T--;)
                if (solve()) printf("YES\n");
                else printf("NO\n");

//	for (scanf("%d",&T);T--;) solve();

//	solve();
	return 0;
}

B Rebellion

题目大意

给定一个长度为 nn 的数组 a1,a2,...,ana_1,a_2,...,a_n,每个元素的值为 0 或 1。定义单次操作分以下三个步骤:

  1. 选择两个下标 1i,jn1\le i,j\le niji\neq j
  2. aj=aia_j=a_i
  3. 从数组中删除 aia_i,且数组长度 nn 减小 1。

操作后数组元素可以大于 1。

问至少操作多少次后数组单调不降。

思路

双指针把原数组的 1 全堆到数组的末尾。

代码

#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int a[N];
int solve()
{
	scanf("%d",&n);
	int ans=0;
	for (int i=1;i<=n;++i) scanf("%d",&a[i]);
	for (int i=1,j=n;i<=j;)
	{
		if (a[i]==0) i++;
		else if (a[j]==1) j--;
		else
		{
			i++;
			j--;
			ans++;
		}
	}
	printf("%d\n",ans);
	return 0;
//	scanf("%d",&k);
}
int main()
{
	int T=1;
	for (scanf("%d",&T);T--;) solve();
	return 0;
}

C Permutation Operations

题目大意

对一个 11nn 的排列 a1,a2,...,ana_1,a_2,...,a_n 进行 nn 次操作,第 ii 次操作可以选择一个下标 kk,让 aj=aj+i(kjn)a_j=a_j+i(k\le j\le n)。一个下标可以多次被选择。

求最小化逆序对数的后缀选择方案。

思路

显然经过 ii 次操作后逆序对数最后一定是 00

合法解很多,一种可行的方案是是给 ii 后面所有的元素加上一个大于 a[i]min{a[i+1],...,a[n]}a[i]-min\{a[i+1],...,a[n]\} 的数。

代码

#include <bits/stdc++.h>
#define nn printf("NO\n")
#define yy printf("YES\n")
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
int a[N],v[N],ans[N];
int solve()
{
	scanf("%d",&n);
	for (int i=1;i<=n;++i) v[i]=ans[i]=0;
	int t=1;
	for (int i=1,j;i<=n;++i)
	{
		scanf("%d",&a[i]);
		v[a[i]]=1;
		while (v[t]) t++;
		if (t<a[i])
		{
			for (j=a[i]-t;ans[j];j++);
			ans[j]=i+1;
		}
	}
	for (int i=1;i<=n;++i)
		if (!ans[i]) printf("1 ");
		else printf("%d ",ans[i]);
	printf("\n");
	return 0;
}
int main()
{
	int T=1;
	for (scanf("%d",&T);T--;) solve();
	return 0;
}