源代码:ACM/OpenjudgeNow/Codeforces at master · abmcar/ACM (github.com)
A. Sorting Parts
题目大意:
思路:
如果前半段之中存在一个数大于后半段的其中一个数,则不可能完成排序
可以使用一个前缀最大值和后缀最小值,枚举前半段的长度即可
代码:
void work()
{
cin >> n;
vector<int> nums(n);
vector<int> preMax(n), aftMin(n);
for (int i = 0; i < n; i++)
cin >> nums[i];
preMax[0] = nums[0];
aftMin[n - 1] = nums[n - 1];
for (int i = 1; i < n; i++)
preMax[i] = max(nums[i], preMax[i - 1]);
for (int i = n - 2; i >= 0; i--)
aftMin[i] = min(nums[i], aftMin[i + 1]);
for (int i = n - 2; i >= 0; i--)
if (preMax[i] > aftMin[i + 1])
{
// cout << preMax[i] << " "<< aftMin[i] << endl;
// cout <<i << endl;
cout << "YES" << endl;
return;
}
cout << "NO" << Endl;
}
B.MEX and Array
题目大意:
思路:
把问题分开来看,如果我们得到了一个子串,那么他最佳分割时的mex是多少?
我们知道任何非0数的单独的mex为0,0的单独mex为1,{0,1}的mex为2
发现分为长度为1的子段时,mex和最小,此时mex和为0的个数
因此我们枚举每一个区间,判断其中0的个数即可,因为n只有100,所以可以暴力
代码:
int getValue(vector<int> nowNums)
{
int nowAns = nowNums.size();
for (int it : nowNums)
if (it == 0)
nowAns++;
return nowAns;
}
void work()
{
cin >> n;
ans = 0;
vector<int> nums(n);
for (int i = 0; i < n; i++)
cin >> nums[i];
for (int len = 1; len <= n; len++)
{
for (int str = 0; str+len <= n; str++)
{
vector<int> temp(len);
for (int nowPos = 0; nowPos < len; nowPos++)
{
temp[nowPos] = nums[str+nowPos];
}
ans += getValue(temp);
}
}
cout << ans << endl;
}
C.Andrew and Stones
题目大意:
思路:
最简单的情况,中间的数全部是2的倍数,我们可以把其中1个放首位,1个放末尾
如果中间有不是1的倍数,怎么办?
如果中间还有别的数进行操作,我们可以把这堆石子的其中一个给不是2的倍数的石堆
如果没有别的数进行操作,且该石堆可以操作1次以上,总长度大于4,可以让该石堆给另一个中间的石堆2个,这个石堆再给原石堆一个
代码:
void work()
{
cin >> n;
vector<int> nums(n), opts(n);
for (int i = 0; i < n; i++)
cin >> nums[i];
int ans = 0;
int oriAns = 0;
int st = 0;
for (int i = 1; i < n - 1; i++)
{
opts[i] = (nums[i] - nums[i] % 2) / 2;
nums[i] = nums[i] % 2;
ans += opts[i];
st += (nums[i] == 1);
}
oriAns = ans;
for (int i = 1; i < n - 1; i++)
{
if (nums[i] == 0)
continue;
if (oriAns - opts[i] > 0 || (n >= 4 && opts[i] >= 1))
{
ans++;
}
else
{
cout << -1 << endl;
return;
}
}
cout << ans << endl;
}
D.Yet Another Minimization Problem
题目大意:
思路:
通过计算,化简可得,成本和数组的和成正相关
由基本不等式可以想到,二者差越小,成本和越小
剩下的问题可以用01背包来解决
代码:
void work()
{
cin >> n;
vector<int> na(n), nb(n);
vector<pair<int, int>> nd(n);
for (int i = 0; i < n; i++)
cin >> na[i];
for (int i = 0; i < n; i++)
cin >> nb[i];
unordered_map<int, int> dp[n];
dp[0][na[0]] = na[0] - nb[0];
dp[0][nb[0]] = nb[0] - na[0];
for (int i = 1; i < n; i++)
{
for (auto it : dp[i - 1])
{
dp[i][it.first + na[i]] = 1e15;
dp[i][it.first + nb[i]] = 1e15;
}
for (auto it : dp[i - 1])
{
dp[i][it.first + na[i]] = min(dp[i][it.first + na[i]], it.second + na[i] - nb[i]);
dp[i][it.first + nb[i]] = min(dp[i][it.first + nb[i]], it.second + nb[i] - na[i]);
}
}
int d = 1e15;
int totA, totB;
for (auto it : dp[n - 1])
{
if (abs(it.second) < d)
{
d = abs(it.second);
totA = it.first;
totB = it.first - it.second;
}
}
int ans = 0;
for (int i = 0; i < n; i++)
ans += na[i] * na[i] + nb[i] * nb[i];
ans *= (n - 2);
ans += totA * totA + totB * totB;
cout << ans << endl;
}