题目链接:https://codeforces.com/contest/1851
A. Escalator Conversations
题意:给定小弗身高h,在扶梯上有n名乘客(不包括小弗),m级扶梯,每级扶梯高度为k,当乘客与小弗的高度差==他们之间扶梯的高度差时,他们可以做到单独交流,问小弗在扶梯上能与多少人聊天。
思路:当小弗与其他乘客的高度差为扶梯高度的倍数,且最高要小于m级扶梯的高度差(等于最高扶梯高度差时,小弗与乘客不会都在扶梯上),高度差不能为0是可以进行交流。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 200100;
int q[N];
int main()
{
int t;
cin >> t;
while(t --)
{
int n, m, k, h;
cin >> n >> m >> k >> h;
int cnt = k * m;
for(int i = 0; i < n; i ++)
{
int x;
cin >> x;
q[i] = abs(x - h);
}
int ans = 0;
for(int i = 0; i < n; i ++)
{
if(q[i] % k == 0 && q[i])
{
if(q[i] < cnt)
res ++;
}
}
cout << ans << endl;
}
return 0;
}
B. Parity Sort
题意:给定长度为n的整数数组a,通过对调任意两个元素,且对调元素必须同时为偶数或奇数,判断最终是否可以使数组变成非递减排序。
思路:通过sort找到在非递减排序下当前位置数x应该在哪个位置,然后比较sort前x应该进行交换的位置的数y。若x与y非均为奇数或偶数,则该数组无法变成非递减排序;反之,若所有数都可以回到排序后的位置,则可以变成非递减排序。这里用的pair来存。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 200100;
PII q[N];
int a[N];
int main()
{
int t;
cin >> t;
while(t --)
{
int n, x = 0, y = 0;
cin >> n;
for(int i = 0; i < n; i ++)
{
int tt;
cin >> tt;
if(tt % 2 == 0) x ++;
else y ++;
q[i].first = tt;
q[i].second = i;
a[i] = tt;
}
int flag = 0;
if(!x || !y)
cout << "YES" << endl;
else
{
sort(q, q + n);
for(int i = 0; i < n; i ++)
{
int u = q[i].first, v = a[i];
if(u % 2 == 0 && v % 2 != 0 || u % 2 == 0 && v % 2 != 0)
{
flag = 1;
break;
}
}
if(flag)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
}
return 0;
}
C. Tiles Comeback
题意:小弗需要经过n块瓷砖,每块瓷砖颜色不同(可以相等)。开始时站在第一块瓷砖上,站过的瓷砖算做一个路径,路径被分为多个区块,每个区块中的颜色相同,小弗需要做到每个区块的瓷砖数为k,且最终路径即踩过的瓷砖数可被k整除。
思路:第一块和最后一块瓷砖是一定要踩的,所以需要找这两种颜色的瓷砖各自是否有k个,且不能相交,若颜色相等的话,只需要找一种颜色是否有k个即可。
开始用map存了一下瓷砖同一颜色的数量,起始和最终的瓷砖有一个不够就直接判,再开一个双指针走一遍就行了。
#include<bits/stdc++.h>
using namespace std;
const int N = 200100;
int q[N];
int main()
{
int t;
cin >> t;
while(t --)
{
map<int, int> mp;
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i ++)
{
cin >> q[i];
mp[q[i]] ++;
}
if(mp[q[1]] < k || mp[q[n]] < k)
cout << "NO" << endl;
else if(q[1] == q[n] && mp[q[1]] >= k)
cout << "YES" << endl;
else
{
int a = q[1], b = q[n], l = 1, r = n;
int aa = 0, bb = 0;
int flag = 0;
while(l < r)
{
if(q[l] == a)
aa ++;
if(q[r] == b)
bb ++;
if(aa < k)
l ++;
if(bb < k)
r --;
if(aa >= k && bb >= k)
{
flag = 1;
break;
}
}
if(flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
return 0;
}
D. Prefix Permutation Sums
题意:有一个有n个元素的数组,数组是从1到n(不一定为顺序)。现在已知该数组的前缀和数组,且丢了一个元素,判断该存不存在一种数组符合该前缀和数组。
思路:差分,用map记录前缀和数组相邻元素第一次出现的差,若存在两个及以上则不存在达成条件的数组构成前缀和,若不存在,则说明缺少最后一个,可任意增补。最多会出现一个大于n的差,然后记录该差tt,累加未出现元素的和sum,若sum==tt,则可以构成,否则不行。这里用等差数列的公式多写了一步,前缀和最大元素不会超过1到n的和。
注意数据会爆int,需要开longlong!!!
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200100;
LL q[N];
int main()
{
int t;
cin >> t;
while(t --)
{
map<int, int> mp;
LL n;
cin >> n;
for(int i = 1; i < n; i ++)
cin >> q[i];
LL cnt = ((n * n) + n) / 2;
q[0] = 0;
if(q[n - 1] > cnt)
cout << "NO" << endl;
else
{
LL ok = 0, flag = 0, tt, u;
for(int i = 1; i < n; i ++)
{
u = q[i] - q[i - 1];
if(!mp[u] && u >= 1 && u <= n)
mp[u] ++;
else
{
ok ++;
tt = u;
}
}
if(ok > 1)
cout << "NO" << endl;
else if(!ok)
cout << "YES" << endl;
else
{
int res = 0;
for(int i = 1; i <= n; i ++)
{
if(!mp[i])
res += i;
}
if(tt == res)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
}
return 0;
}