CF Round 656
A: Three Pairwise Maximums
$\color{red}入门-模拟$
题目翻译
给你3个质数 $x,y,z$ ,和他们的算法 $x = max (a,b); y = max (a,c); z = max (b,c)$ ,请你算出 $a,b,c$ 。
做法
- 如果 $x=y=z$ ,直接输出3个 $x$ 因为不管怎么样,当 $x=y=z$ 的时候做 $max$ 运算时,答案一定是 $x$ 或 $y$ 或 $z$
- 如果 $x=y$ 而且 $x(y)$ 最大,直接输出 $x,z,z$ ($a=x, b=y=c=z$)
- 如果 $x=z$ 而且 $x(z)$ 最大,直接输出 $y,x,y$ ($a=y, b=x=c=y$)
- 如果 $y=z$ 而且 $y(z)$ 最大,直接输出 $x,x,y$ ($a=x=b=x, c=y$)
- 否则直接输出
NO
Code
// CF 1385 A Three Pairwise Maximums
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int t, x, y, z, a, b, c;
int main (){
scanf ("%d", &t);
while (t --)
{
scanf ("%d%d%d", &x, &y, &z);
if (x == y && x == z)
{
printf ("YES\n%d %d %d\n", x, x, x);
continue;
}
if (x == y && x > z)
{
printf ("YES\n%d %d %d\n", x, z, z);
continue;
}
if (x == z && x > y)
{
printf ("YES\n%d %d %d\n", y, x, y);
continue;
}
if (y == z && y > x)
{
printf ("YES\n%d %d %d\n", x, x, y);
continue;
}
printf ("NO\n");
}
return 0;
}
B: Restore the Permutation by Merger
$\color{red}入门-模拟/统计$
题目翻译
说白了就是给你含有 $n$ 个整数的数组 $a$ ,让你去数有多少个 $x$ ,而且保留它的位置。
做法
定义一个结构体 Count
,含有 int a
int pos
。
- $Count_a$ 表示这个数
- $Count_{pos}$ 表示这个数的位置
struct Count
{
int a, pos;
bool operator < (const Count &a) const
{
return pos < a.pos;
}
};
bool operator < (const Count &a) const;
是一个方便 $sort$ 快排的函数。
在每次输入时将 $x$ 放进 Count
结构体里,但是由于这个题的数会重复,所以放之前还得加一个判断 if (a[x].pos == 0)
排序后按顺序输出即可。
Code
// CF 1385 B Restore the Permutation by Merger
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Count
{
int a, pos;
bool operator < (const Count &a) const
{
return pos < a.pos;
}
};
int n, t, cnt;
Count a[105];
int main ()
{
scanf ("%d", &t);
while (t --)
{
scanf ("%d", &n);
memset (a, 0, sizeof (a));
cnt = 0;
for (int i = 0; i < n * 2; i ++)
{
int x;
scanf ("%d", &x);
if (a[x].pos == 0)
{
a[x].pos = ++ cnt;
a[x].a = x;
}
}
sort (a + 1, a + cnt + 1);
for (int i = 1; i <= cnt; i ++)
{
printf ("%d ", a[i].a);
}
printf ("\n");
}
return 0;
}
C: Make It Good
$\color{orange}普及-模拟/贪心$
题目翻译
有一个操作:给你一个数列,让你把最前面或最后面尽量小的数放到新的数列里,让这个新的数列满足 $a_i=a_{i-1}$
给你一个数列,让你从前面删掉几个数使上面的操作成立。
做法
咱们试试看
4 3 3 8 4 5 2
那么删掉前面 4 个数 4 3 3 8
就能使后面的 4 5 2
成立,因为通过上面那个操作能把 4 5 2
变成 2 4 5
。
左面的是原来的序列,右面的是新产生的数列。
[4 5 2] / []
[4 5] / [2]
[5] / [2 4]
[] / [2 4 5]
2 4 5
就是什么Good数列。
其实可以把像 4 5 2
这样的数列想象成 $4<=5>=2$ 即 $a_1<=...<=a_{i-1}<=a_{i}>=a_{i+1}>=...>=a_n$
所以这题用模拟指针的方法去做比较容易。
因为这个题要从前面往后面删除数,所以应该从后面开始算。
先用一个循环去算 $a_i$ 到 $a_n$ 之间,然后再用一个循环去算 $a_i$ 到 $a_{del}$ 之间(这里的 $del$ 代指的是要删除的位置后一个位置)
所以这两个循环就是这样的
while (n > 1 && a[n - 1] >= a[n]) -- n;
while (n > 1 && a[n - 1] <= a[n]) -- n;
上面说的 $del$ 其实就是现在这两个 while
之后算出来的 $n$ 。
Code
// CF 1385 C Make It Good
#include <iostream>
#include <cstdio>
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 ++)
scanf ("%d", &a[i]);
while (n > 1 && a[n - 1] >= a[n]) -- n;
while (n > 1 && a[n - 1] <= a[n]) -- n;
printf ("%d\n", n - 1);
}
return 0;
}
写在后面的话
- 第三题的代码比前俩题都短一些
- 第一题还是最简单
- 有严重的语言障碍
/嘻嘻 /太难了 /语言障碍啊
- 分类: 题解 Codeforces
- 标签: Codeforces CF题解
- 浏览: 80