Codeforces Global Round 15


A、Subsequence Permutation

题目链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值