Codeforces Global Round 9 A ~ D 题解


A - Sign Flipping

题面

题意简述:

给定长为 \(n\)\(n\) 是奇数)的整数数组 \(a\),你可以进行任意次操作,每次选择一个 \(a_i\) 并将它变成 \(-a_i\)。你需要让最终的数组满足以下条件:

  • 至少有 \(\frac{n-1}{2}\) 个相邻数的差值 \(\le 0\)
  • 至少有 \(\frac{n-1}{2}\) 个相邻数的差值 \(\ge 0\)

输出任意一个满足条件的最终数组。如果有多个解,输出任意一个,可以证明,解总是存在的。

多组测试数据。

\(\texttt{Data Range:} 1\le t\le 500, 3\le n\le 99, -10^9\le a_i\le 10^9\)

简单构造。

一正一负即可。

const int N = 103;

int n, a[N];

int main()
{
    int T = gi();
    while (T--)
    {
    	n = gi();
    	for (int i = 1; i <= n; i+=1) a[i] = gi();
    	for (int i = 1; i <= n; i+=1)
    	{
    		if (i & 1) printf("%d ", -abs(a[i]));
    		else cout << abs(a[i]) << ' ';
    	}
    	puts("");
    }
    return 0;
}

B - Neighbor Grid

题面

题意简述:

给你一个 \(n\)\(m\) 列的矩阵,要求你让这个矩阵是“完美”的。

“完美”的定义如下:

若当前的格子里是一个正整数 \(k\),那么与这个网格相邻(有公共边)的 \(k\) 个格子也必须有一个正整数。

若当前的格子里是 0 ,那么不受上述的限制。

你可以对任意的一个格子加上 1 ,次数不受限制。

如果可以做到“完美”,请输出 YES 之后,将修改过的矩阵输出。

否则只输出一行 NO

多组测试数据。

\(\texttt{Data Range:}1\le t\le 5000, 2\le n,m\le 300,n\times m\le 10^5,0\le a_{i,j}\le 10^9\)

简单构造。

每个角上的数为 \(2\),每个边上的数为 \(3\),中间的数为 \(4\),无解判断一下即可。

const int N = 303;

int n, a[N][N];

int main()
{
    int T = gi();
    while (T--)
    {
    	n = gi(), m = gi();
    	for (int i = 1; i <= n; i+=1)
    		for (int j = 1; j <= m; j+=1)
    			a[i][j] = gi();
    	bool ok = true;
    	if (a[1][m] > 2 || a[n][1] > 2 || a[n][m] > 2 || a[1][1] > 2)
    	{
    		puts("NO");
    		continue;
    	}
    	for (int i = 2; i < m; i+=1)
    	{
    		if (a[1][i] > 3 || a[n][i] > 3) ok = false;
    	}
    	for (int i = 2; i < n; i+=1)
    		if (a[i][1] > 3 || a[i][m] > 3) ok = false;
    	for (int i = 2; i < n; i+=1)
    		for (int j = 2; j < m; j+=1)
    			if (a[i][j] > 4) ok = false;
    	if (!ok) puts("NO");
    	else 
    	{
    		puts("YES");
    		a[1][m] = a[n][1] = a[n][m] = a[1][1] = 2;
    		for (int i = 2; i < m; i+=1)
    			a[1][i] = 3, a[n][i] = 3;
			for (int i = 2; i < n; i+=1)
				a[i][1] = 3, a[i][m] = 3;
			for (int i = 2; i < n; i+=1)
				for (int j = 2; j < m; j+=1)
					a[i][j] = 4;
			for (int i = 1; i <= n; i+=1)
			{
				for (int j = 1; j <= m; j+=1)
					cout << a[i][j] << ' ';
				puts("");
			}
    	}
    }
    return 0;
}

C - Element Extermination

题面

题意简述:

给定一个 \(1\)\(n\)排列 \(a\)。在一次操作中,你可以选择一个满足 \(a_i 的下标 \(i(1 \leq i,删除 \(a_i\)\(a_{i+1}\)

你需要求出是否可能通过若干次操作使得 \(a\) 只剩下一个元素。

多组测试数据。

\(\texttt{Data Range:}1\le t\le 2\times 10^4,2\le n\le 3\times 10^5,\sum n\le 3\times 10^5,1\le a_i\le n\)

结论是 \(a_1 < a_n\) 就有解,否则无解。

证明留给读者作为练习。

const int N = 300003;

int n, m;
int a[N];

int main()
{
    int T = gi();
    while (T--)
    {
    	n = gi();
    	for (int i = 1; i <= n; i+=1) a[i] = gi();
    	if (a[1] < a[n]) puts("YES");
    	else puts("NO");
    }
    return 0;
}

D - Replace by MEX

题面

题意简述:

给一个序列 \(a\),每次操作可以选定一个位置 \(p\),令 \(a_p=\) 这个序列的 \(\text{MEX}\)。你需要进行若干次操作,使得这个序列单调不降。操作次数不能超过 \(2\times n\)

多组测试数据。

\(\texttt{Data Range:}1\le t\le 200,n \leq 1000,a_i \in [0,n]\)

考虑把原序列变成 \(0,1,\dots,n-1\)

每一次求出序列的 \(\text{MEX}\),如果 \(\text{MEX}=n\),那么找到一个没有匹配上的数将它替换;否则将 \(a_{\text{MEX}+1}\) 替换成 \(\text{MEX}\)

const int N = 1003;

int n, m, a[N], ton[N];

inline bool check()
{
	for (int i = 1; i < n; i+=1) 
    	if (a[i] > a[i + 1])
    		return false;
    return true;
}

inline int MEX()
{
	for (int i = 0; i <= n; i+=1)
		if (!ton[i]) return i;
}

int main()
{
    int T = gi();
    while (T--)
    {
    	n = gi();
    	for (int i = 1; i <= n; i+=1) a[i] = gi();
    	if (check()) {puts("0\n"); continue;}
    	vector  ans;
    	while (1)
    	{
    		if (check()) break;
    		for (int i = 0; i <= n; i+=1) ton[i] = 0;
    		for (int i = 1; i <= n; i+=1)
    			++ton[a[i]];
    		int now = MEX();
    		if (now == n)
    		{
    			for (int i = 1; i <= n; i+=1)
    				if (a[i] != i - 1)
    				{
    					a[i] = now;
    					ans.push_back(i);
    					break;
    				}
    		}
    		else 
    		{
    			a[now + 1] = now;
    			ans.push_back(now + 1);
    		}
    	}
    	cout << ans.size() << endl;
    	for (auto x : ans) cout << x << ' ';
    	puts("");
    }
    return 0;
}