2019 ICPC Universidad Nacional de Colombia Programming Contest(2020.4.12)
B、Boring Non-Palindrome
找最长回文后缀。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool check(const char *s, int p)
{
int l = p, r = strlen(s) - 1;
while (l <= r)
{
if (s[l] == s[r]) ++l, --r;
else return 0;
}
return 1;
}
int main()
{
char s[5050]; cin >> s;
int pos, len = strlen(s);
for (int i = 0; i < len; ++i)
if (check(s, i))
{
pos = i; break;
}
cout << s;
for (int i = pos - 1; i >= 0; --i) cout << s[i];
cout << endl;
return 0;
}
G、Graduation
这题比较有意思。若某节课是另一节课的先修课我们就连边,并且把先修课作为这门课的父节点,最后我们得到一片森林。
如果某一门先修课已经被修完了,那我们就把这个父节点拆掉,用它的所有孩子顶替它。这样我们每次只能在这片森林的第一层选课。
考虑贪心。为了尽可能用少的学期上完所有课,我们每次尽量选树深大的节点。其实很好想到,因为如果没有 k k k的限制,那么最少学期就是这片森林里的最大树深。现在我们把树深大的尽量选在前面上,防止之后产生其它课上完了但是剩下的课必须要修完先修课而导致答案变大的情况。
(P.S. 一开始我想的是优先拓展孩子数多的,结果WA10了…后来想想着实不对,如果有一个根节点屁股后面跟了巨多孩子就错了)
然后搞个优先队列模拟一下过程就可以了。注意要提前把树深算出来。 O ( n l o g n ) O(nlogn) O(nlogn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e4 + 10;
vector <int> tree[MAXN];
int height[MAXN] = {0};
struct node
{
int num;
};
bool operator < (node a, node b)
{
return height[a.num] < height[b.num];
}
int dfs(int root)//求树深
{
if (tree[root].size() == 0) return height[root] = 1;
int maxi = -1;
for (int i = 0; i < tree[root].size(); ++i)
height[tree[root][i]] = dfs(tree[root][i]), maxi = max(maxi, height[tree[root][i]]);
return height[root] = maxi + 1;
}
int main()
{
int n, k; cin >> n >> k;
static int a[MAXN];
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
tree[a[i]].push_back(i);
}
for (int i = 0; i < tree[0].size(); ++i) dfs(tree[0][i]);
/*for (int i = 1; i <= n; ++i) cout << height[i] << ' ';
cout << endl;*/
priority_queue <node> que; int ans = 0;
for (int i = 0; i < tree[0].size(); ++i) que.push({tree[0][i]});
while (!que.empty())
{
int sav = 0;
vector <node> x;
while (sav < k && !que.empty())
{
++sav;
x.push_back(que.top()); que.pop();
}
for (int i = 0; i < x.size(); ++i)
for (int j = 0; j < tree[x[i].num].size(); ++j)
que.push({tree[x[i].num][j]});
++ans;
}
cout << ans << endl;
return 0;
}
I、Integer Prefix
乱搞一下就好了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
string t; cin >> t;
bool f = 0;
for (int i = 0; i < t.length(); ++i)
if (t[i] >= '0' && t[i] <= '9')
{
cout << t[i]; f = 1;
}
else break;
if (!f) cout << -1;
cout << endl;
return 0;
}
K、Kernel Of Love
这第四个条件的意思就是选择相邻的 x , y x,y x,y。懒得去想证明了,所以写个暴搜找找规律,然后就做出来了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
static ll f[100010] = {0, 0, 0, 2};
for (int i = 1; 3 * i <= 100010; ++i)
{
f[3 * i + 1] = f[3 * i] + 1;
f[3 * i + 2] = f[3 * i + 1];
f[3 * i + 3] = f[3 * i + 2] + 1;
}
int t; cin >> t;
while (t--)
{
int n; scanf("%d", &n);
printf("%lld\n", f[n]);
}
return 0;
}