A、Subsequence Permutation
题意:你有一个序列a,你现在可以选择a中一个不连续的子序列b,对子序列按照字典序排序后依次放回序列a,使得a序列是按照字典序顺序的,要求求出b序列的最小长度。
思路:我们可以很容易的想到,如果按照字典序排序的a序列变成了了c,那么b序列的最小值,便是a和c序列相同位置上面的不同字母总数是多少。
吐槽:自己写的有点麻烦了,其实还可以更加的简略。
代码:
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
char ch[5000];
int main ()
{
int t, n;
cin >> t;
while(t--)
{
cin >> n;
string s;
cin >> s;
for(int i = 0; i < n; i++)
{
ch[i] = s[i];
}
sort(ch, ch+n);
int cnt = 0;
for(int i = 0; i < n; i++)
{
if (ch[i] != s[i])
{
cnt ++;
}
}
cout << cnt << endl;
}
return 0;
}
B、Running for Gold
题目链接:Running for Gold
题意:一共有n个运动员,现在每个运动员已经有五场比赛的成绩(每场比赛成绩唯一,不会出现重复排名),我们规定如果运动员A的五场比赛中有3场及以上的比赛排名要高于运动员B,那么我们认为运动员A是比运动B更有希望拿到金牌的,显然的,当出现一个运动员比其他所有运动员都有可能拿到金牌,则他就是最可能获得金牌的运动员,现在要求出这个运动员的编号,如果没有就输出-1.
思路:我刚开始没什么思路,一来就是直接莽的结构体排序。别人提醒了,我才知道正确的解法。一个词:“擂台赛”,如果一个人真的能获得金牌,那么他一定可以打败所有人,当然为了保险,我们第一次循环找到这个人,之后再进行一次循环,确认他是否能打败所有的人。
吐槽:全球场果然有些许自闭,写完B我就停了,卡C了。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct p
{
int a, b, c, d, e, num;
};
p x[50005];
int t, n;
int main ()
{
cin >> t;
while(t--)
{
cin >> n;
for(int i = 1;i <= n; i++)
{
cin >> x[i].a >> x[i].b >> x[i].c >> x[i].d >> x[i].e;
x[i].num = i;
}
p now = x[1];
for(int i = 2; i <= n; i++)
{
int win = 0, loss = 0;
if(now.a < x[i].a) win++;
else loss++;
if(now.b < x[i].b) win++;
else loss++;
if(now.c < x[i].c) win++;
else loss++;
if(now.d < x[i].d) win++;
else loss++;
if(now.e < x[i].e) win++;
else loss++;
if (loss >= 3)
{
now = x[i];
}
}
int f = 1;
for(int i = 1; i <= n; i++)
{
if (i != now.num)
{
int win = 0, loss = 0;
if(now.a < x[i].a) win++;
else loss++;
if(now.b < x[i].b) win++;
else loss++;
if(now.c < x[i].c) win++;
else loss++;
if(now.d < x[i].d) win++;
else loss++;
if(now.e < x[i].e) win++;
else loss++;
if (loss >= 3)
{
f = 0;
break;
}
}
}
if (f==1 || n == 1)
{
cout << now.num << endl;
}
else
{
cout << -1 << endl;
}
}
return 0;
}
C、Maximize the Intersections
题目链接:Maximize the Intersections
题意:众所周知:圆上不相同的两点连成一条弦,多条弦可能相交也可以不相交。现在给出n对点,和已经相连的了k条弦,接下里k对顶点,表示一条弦。剩下来n-k对点,要求你把它们连成弦,相交的交点最多。输出交点的数量。
思路:我们对k为0的情况进行思考,在这时,一定有一个最优解,例如n=3的时候,我们按照顺时针命名点依次为1-6;连接1-4、2-5、3-6,交点数量是3。同理可以推,当只剩下n-k对点的时候,我们按照刚刚的方法把剩下的点连接起来,再计算总数就可以得到答案。
吐槽:我在后面的数点中,错误的把2*n单写了成n,因此我没交上去。其实我自己都觉得自己不太对,因为我感觉我没有对全局进行思考,只是对剩下的点进行了最大化,后面看题解,意思都差不多。最后检查代码,才发现是循环上限的问题。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
int a[2000], n, k, t, b[2000];
int main ()
{
cin >> t;
while(t--)
{
cin >> n >> k;
for(int i = 1; i <= 2*n; i++)
{
a[i] = i;
check[i] = 0;
}
for(int i = 1; i <= k; i++)
{
int x, y;
cin >> x >> y;
a[y] = x;
a[x] = y;
}
int cnt = 1;
for(int i = 1; i <= n*2; i++)
{
if (a[i] == i)
{
b[cnt++] = a[i];
}
}
for(int i = 1; i <= cnt/2; i++)
{
int x = b[i], y = b[cnt/2+i];
a[x] = y;
a[y] = x;
}
int ans = 0;
for(int i = 1;i <= n*2; i++)
{
int l = i + 1, r = a[i]-1, sum = 0;
for(int j = l; j <= r; j++)
{
if (a[j]<i || a[j] > a[i])
{
sum++;
}
}
ans += sum;
}
cout << ans/2 << endl;
}
return 0;
}