寒假训练第二天-Codeforces Round #498 (Div. 3)
前言:昏昏沉沉的一天,最近外婆生病,每天上午都在陪外婆输液,每到冬天感觉家里的老人都衰老了好多,希望外婆病赶快好身体健健康康的
题目链接-https://codeforces.com/contest/1006
A-Adjacent Replacements
题意:给你一个序列,然后用i代替序列中的i - 1,再用i - 1代替数列中的i(i为偶数)
题解:奇数i - 1被偶数i代替之后又被奇数i - 1代替成偶数,偶数被奇数i - 1代替,所以数列中的奇数不变,偶数减一
int a[1010];
int32_t main()
{
ICO;
int n;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
if(a[i] & 1) cout << a[i] << ' ';
else cout << a[i] - 1 << ' ';
}
return 0;
}
B-Polycarp’s Practice
题意:给你n个数,让你按顺序将这n个数分成k段,使分成k段后每段价值和最大。价值:每段的价值等于每段序列中的最大数。求最大价值及每段序列的长度。
题解:找出这个序列的前k大数并记录下标,将下标排序后输出即可,注意最后一段的长度为总长度减去倒数第二个下标。
int a[2020];
vector<int> v;
vector<pair<int, int> > t;
int32_t main()
{
ICO;
int n, k, res = 0;
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
t.push_back({
a[i], i});
}
sort(t.begin(), t.end());
v.push_back(0);
for(int i = n - k; i < n; i++)
{
res += t[i].first;
v.push_back(t[i].second);
}
cout << res << endl;
sort(v.begin(), v.end());
for(int i = 1; i < k; i++)
cout << v[i] - v[i - 1] << ' ';
cout << (n - v[k - 1]) << endl;
return 0;
}
C-Three Parts of the Array
题意:将一个序列分成三段,使第一段的和等于第三段的和(每段和可为0),求满足条件的第一段和的max。
题解:将前缀和和后缀和算出来,在后缀和中查找前缀和(倒叙查找)。
const int maxn = 2e5 + 10;
int a[maxn];
ll l[maxn], r[maxn];
int32_t main()
{
ICO;
int n;
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
for(int i = 1; i <= n; i++)
{
l[i] = l[i - 1] + a[i];
r[i] = r[i - 1] + a[n - i + 1];
}
for(int i = n; i >= 1; i--)
{
bool ok = binary_search(r + 1, r + n + 1, l[i]);
if(ok && i + (lower_bound(r + 1, r + n + 1, l[i]) - r) <= n)
{
cout << l[i] << endl;
return 0;
}
}
cout << 0 << endl;
return 0;
}
D-Two Strings Swaps
题意:两个字符串,从中间对折后,对第一个字符串进行更换字母,使两个字符串相等,求最小更换的字符个数。
题解:读错题了,理解成了对两个字符串进行更换字母,然后各种wa,人都wa傻了。说一下该题需要注意的点:1.n为奇数时只要两个字符串中间的字母不相同就需要更换一个;2.对折后的字符串若对应列只有三个字符,要考虑相同字符是否在第一个字符串上,若在则需要更改两个字符,否则更改一个即可。
string s[4];
int cnt[30];
int32_t main()
{
ICO;
int n, res = 0;
cin >> n >> s[0] >> s[1];
//a = "0" + a, b = "0" + b;
s[2] = s[0], s[3] = s[1];
reverse(s[2].begin(), s[2].end()), reverse(s[3].begin(), s[3].end());
for(int i = 0; i < (n >> 1); i++)
{
mem(cnt, 0);
for(int j = 0; j < 4; j++)
cnt[s[j][i] - 'a']++;
int num = 0;
for(int j = 0; j < 26; j++)
if(cnt[j] & 1) num++;
bool ok;
if(num == 2)
{
ok = 0;
for(int j = 0; j < 26; j++)
{
if(cnt[j] == 2)
{
ok = 1;
break;
}
}
if(ok && (s[0][i] == s[2][i])) res += 2;
else res++;
}
else if(num == 4) res += 2;
}
if(n & 1 && s[0][n >> 1] != s[1][n >> 1]) res++;
cout << res << endl;
return 0;
}
E-Military Problem
题意:给你一棵树,对树进行dfs,每次告诉你dfs的起点和遍历的步数,问是否能遍历这么多步,能则输出终点,不能输出-1。
题解:对树进行dfs遍历即可,记录到达一个点需要的步数和走若干步到达的点即可。
const int maxn = 2e5 + 10;
vector<int> v[maxn];
int u, k, cnt;
int p[maxn], q[maxn], res[maxn];
void dfs(int d)
{
q[d] = 1;
p[d] = ++cnt;
res[cnt] = d;
for(int i = 0; i < v[d].size(); i++)
{
dfs(v[d][i]);
q[d] += q[v[d][i]];
}
}
int32_t main()
{
ICO;
int n, t, x;
cin >> n >> t;
for(int i = 2; i <= n; i++)
{
cin >> x;
v[x].push_back(i);
}
dfs(1);
while(t--)
{
cin >> u >> k;
if(q[u] < k) cout << -1 << endl;
else cout << res[p[u] - 1 + k] << endl;
}
return 0;
}
总结:D题题意理解错导致浪费了大量的时间,果然读好题才能好好写。继续努力。