官方题解 - Presentation of solutions
A - Amusement Anticipation
Gym - 101670A
题意:找一个位置的下标使得从该位置到数组末尾是一个等差数列。
思路:签到题。倒着往前找即可。
AC代码:
# include
# include
using namespace std;
const int MAX = 1e3 + 5;
int number[MAX];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin >> n)
{
for(int i = 1; i <= n; I++)
{
cin >> number[I];
}
int ans = 1;
for(int i = n - 2; i > 0; I--)
{
if(number[i] - number[i + 1] != number[i + 1] - number[i + 2])
{
ans = i + 1;
break;
}
}
cout << ans << endl;
}
}
B - Pond Cascade
Gym - 101670B
AC代码:
# include
# include
# include
using namespace std;
const int MAX = 1e5 + 5;
struct Node
{
void init(long long s, int pr, int no, int ne)
{
finish = false;
speed = s;
baseTime = 0;
finishTime = value / speed;
prev = pr;
now = no;
next = ne;
}
bool finish;
double value;
long long speed;
double baseTime;
double finishTime;
int prev, now, next;
friend bool operator < (Node a, Node b)
{
return a.finishTime > b.finishTime;
}
};
Node node[MAX];
priority_queue order;
int main()
{
int n;
long long f;
while(~scanf("%d%lld", &n, &f))
{
for(int i = 0; i < n; i++)
{
scanf("%lf", &node[i].value);
node[i].init(f, i - 1, i, (i == n - 1? -1: i + 1));
order.push(node[i]);
}
int now, next, prev;
while(!order.empty())
{
now = order.top().now;
order.pop();
if(node[now].finish)
continue;
node[now].finish = true;
next = node[now].next;
prev = node[now].prev;
if(prev != -1)
node[prev].next = next;
if(next != -1)
node[next].prev = prev;
if(next != -1)
{
node[next].value -= 1.0 * node[next].speed * (node[now].finishTime - node[next].baseTime);
node[next].baseTime = node[now].finishTime;
node[next].speed += node[now].speed;
node[next].finishTime = node[next].baseTime + node[next].value / node[next].speed;
order.push(node[next]);
}
}
double finishTime = 0, lastTime = node[n - 1].finishTime;
for(int i = 0; i < n; i++)
finishTime = max(finishTime, node[i].finishTime);
printf("%.8f %.8f\n", lastTime, finishTime);
}
}
C - Chessboard Dancing
Gym - 101670C
题意:在n*n的棋盘上摆放舞蹈队伍,不同类型摆放要求不同
思路:画一下就能发现规律了
主要是Knight这个,容易不太好想,其实只要交错填入1、2,就可以了(如下图)
AC代码:
# include
# include
using namespace std;
int main()
{
int n;
char ch;
while(cin >> n >> ch) {
if(ch == 'B' || ch == 'R')
cout << n << endl;
else if(ch == 'K') {
if(n == 1)
cout << 1 << endl;
else
cout << 4 << endl;
}
else if(ch == 'N'){
if(n == 1 || n == 2)
cout << 1 << endl;
else
cout << 2 << endl;
}
}
return 0;
}
D - Equinox Roller Coaster
Gym - 101670D
E - Forest Picture
Gym - 101670E
题意:画森林,m*m的画布,n条绘画指令。指令为s, x, y。s表示树高,x,y是坐标,树可能在画布外面,也有可能一部分在画布外,如果s == 0, 该位置为"_o_"
(树墩),若s > 1,表示树高,有高度的树,树根是"_|_"
,树干是"/|\"
,树顶" ^ "
。
思路:由于,比较有意思的是x,y虽然很大,但是树高S很小,而且绘图纸的大小也很小,所以直接模拟即可
AC代码:
#include
#include
#include
#include
using namespace std;
const int maxn = 150;
char mp[maxn][maxn];
int m, n;
int s, x, y;
void init() {
for(int i = 0; i < m; ++i) {
for(int j = 0; j < m; ++j) {
mp[i][j] = '.';
}
mp[i][m] = '\0';
}
}
bool judge(int x, int y) {
if(x >= 0 && x < m && y >= 0 && y < m)
return true;
return false;
}
bool judgexy(int x) {
if(x >= 0 && x < m)
return true;
return false;
}
void draw() {
if(judge(x-1, y)) mp[y][x-1] = '_';
if(judge(x+1, y)) mp[y][x+1] = '_';
if(s == 0) {
if(judge(x, y)) mp[y][x] = 'o';
}
else {
if(x >= 0 && x < m) {
for(int i = 0; i < s+1; ++i) { //mid
if(y+i >= 0 && y+i < m) {
mp[y+i][x] = '|';
}
}
}
if(judge(x, y+s+1)) {
mp[y+s+1][x] = '^';
}
if(judgexy(x-1)) {
for(int i = 0; i < s; ++i) {
if(judgexy(y+1+i)) {
mp[y+1+i][x-1] = '/';
}
}
}
if(judgexy(x+1)) {
for(int i = 0; i < s; ++i) {
if(judgexy(y+1+i)) {
mp[y+1+i][x+1] = '\\';
}
}
}
}
}
int main() {
while(scanf("%d%d", &m, &n) == 2) {
init();
for(int i = 0; i < n; ++i) {
scanf("%d%d%d", &s, &x, &y);
draw();
}
for(int i = 0; i < m+2; ++i)
printf("*");
printf("\n");
for(int i = m-1; i >= 0; --i) {
printf("*");
printf("%s", mp[i]);
printf("*\n");
}
for(int i = 0; i < m+2; ++i)
printf("*");
printf("\n\n");
}
return 0;
}
F - Shooting Gallery
Gym - 101670F
G - Ice cream samples
Gym - 101670G
题意:n种售卖,k种冰淇淋品牌,每一种售卖有L个冰淇淋,品牌分别为a[0], a[1], a[2], ..., a[k-1]。现在要从一个位置开始买,买尽量少的冰淇淋来集齐k种品牌,问最少要买多少个冰淇淋,如果无法集齐k种品牌,输出-1。
思路:尺取(双指针法)。由于必须连续买,所以就是在确定一个购买起点和一个终点。
H - Dark Ride with Monsters
Gym - 101670H
题意:给出一个1-n的序列,问交换多少次才能得到1-n的正序序列
思路:将给出的序列和正序序列比较,找闭合的环,答案为n-闭合环数量
AC代码:
# include
# include
# include
using namespace std;
const int MAX = 2e5 + 5;
int number[MAX];
bool used[MAX];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin >> n)
{
memset(used, false, sizeof(used));
for(int i = 1; i <= n; i++)
{
cin >> number[i];
}
int ans = 0;
for(int i = 1; i <= n; i++)
{
if(!used[i])
{
int now = i, base = i;
used[now] = true;
while(number[now] != base)
{
now = number[now];
used[now] = true;
}
ans++;
}
}
cout << n - ans << endl;
}
}
I - Go Northwest!
Gym - 101670I
AC代码:
#include
#include
#include
#include
#include
#include
J - Punching Power
Gym - 101670J
题意:给出一些点的坐标,选尽量多的点使得剩下的点两两之间的距离都大于1.3
思路:将不满足距离 > 1.3的点建边跑二分图匈牙利匹配,答案 = 点数 - 匹配数。
建图:奇偶匹配,根据每个点 坐标x+y的奇偶(每个点和与它相临距离 < 1.3 的坐标x+y奇偶性肯定不同) 化为二分图,距离<1.3的(其实就是距离==1的)之间连边,跑匈牙利即可。
AC代码:
#include
#include
#include
#include
#include
#include
K - Treetop Walkway
Gym - 101670K