Codeforces Round 890 (Div. 2) 赛后总结
小菜鸡的赛后总结
A. Tales of a Sort
- 题意:给一个数组,可以执行一个操作:将所有数-1,最低减少到0,执行这个操作直到数组为递增,求出操作次数
- 思路:找逆序对中最大的数即可,比较简单
void BlueFire()
{
int n;
cin >> n;
vector<int> v(n + 1);
int maxnn = 0;
bool flag = 0;
for (int i = 1; i <= n; i++)
{
cin >> v[i];
if (v[i] < v[i - 1])
{
flag = 1;
maxnn = max(v[i - 1], maxnn);
}
}
if (!flag)
{
cout << 0 << endl;
return;
}
else
{
cout << maxnn << endl;
}
return;
}
B. Good Arrays
- 题意:给出一个a数组,求一个b数组,b数组满足两个条件:1.a数组和b数组相同下标的数不能相等。2.a数组的所有数之和与b数组的所有数之和相等。问这样的b数组是否存在(a和b的数都必须是正数)
- 思路:观察样例思考,我们发现只需要在a数组上进行操作即可,既然需要和相等,又需要对应位置不是原来的数,那么可以想到,对于已经为1的数,为了让它变化并且和不变,就需要其他大于1的数分给它至少1,而大于1的数也可以分到直到其减少为1为止,当然,如果a数组里都大于1,也可以集中分到一个数上。所以只需要记录大于1的数以及等于1的数就行了。
void BlueFire()
{
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
ll needF = 0;//需要分的
ll needA = 0;//需要加的
for (int i = 1; i <= n; i++)
{
if (a[i] > 1)
needF += (a[i] - 1);
else
needA++;
}
if (needF >= needA && n != 1)
cout << "Yes" << endl;
else
cout << "No" << endl;
return;
}
C. To Become Max
- 题意:给出一个数组a,你可以对其进行一个操作:
1.选择一个下标i,满足ai<=a(i+1)
2.让ai + 1
在进行最多k次操作后,找到数组a中可能的最大值
- 思路:首先想到,对于一个正序对a[i],a[i+1],k充足的情况下a[i]最多能变为a[i+1],考虑顺序枚举,但是发现a[i]的变化可能会影响到其他逆序对,改变它们的性质。然后逆向思考,如果k充足的情况下a[i]能变为最大值x,那么a[i+1]一定是x-1,a[i+2]一定是x-2...所以可以二分答案,二分这个最大值,每次check枚举每个位置能否在k次内变为最大值。
int a[1010];
int n, k;
bool check(int mid)
{
for (int i = 0; i < n; i++)
{
int t = k;
int ans = mid;
for (int j = i; j < n; j++)
{
if (a[j] >= ans)
return true;
if (t < ans - a[j])
break;
t -= ans - a[j];
ans--;
}
}
return false;
}
void BlueFire()
{
cin >> n >> k;
for (int i = 0; i < n; i++)
cin >> a[i];
int l = *max_element(a, a + n);
int r = 1e9;
while (l < r)
{
int mid = (l + r + 1) / 2;
if (check(mid))
l = mid;
else
r = mid - 1;
}
cout << l << endl;
return;
}