AtCoder Beginner Contest 143

前三道签到

A. Curtain

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 1001

using namespace std;


int main()
{
	int A, B;
	cin >> A >> B;

	if (A - B * 2 <= 0)
		cout << 0 << endl;
	else
		cout << A - B * 2 << endl;

	return 0;
}

B. TAKOYAKI FESTIVAL 2019

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 101

using namespace std;

int d[M];

int main()
{
	int n, sum = 0;
	cin >> n;

	for (int i = 1; i <= n; i++)
		cin >> d[i];

	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++)
			sum += d[i] * d[j];

	cout << sum << endl;

	return 0;
}

C. Slimes

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 101

using namespace std;

int main()
{
	int n, tot = 1;
	char ch,last;

	cin >> n;
	cin >> last;

	for (int i = 2; i <= n; i++)
	{
		cin >> ch;
		if (ch == last)
			continue;
		else
		{
			tot++;
			last = ch;
		}
	}

	cout << tot << endl;

	return 0;
}

D. Triangles

从一个数组中选三个数,问最多能组成多少个三角形。
本来是很简单的题,先排序,然后枚举两条边,二分查找第三条边就行了,复杂度O(n2log n),结果二分写了半天,还没考虑到重复的情况,WA了3次,浪费了大量时间,真是醉了。早知道还不如用upper_bound。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 2001

long long L[M];
long long n;

using namespace std;

long long check(long long i, long long j)
{
	long long ans = L[i] + L[j] - 1;
	long long l = j + 1, r = n;
	while (l <= r)
	{
		long long mid = (l + r) / 2;
		if (L[mid] == ans)
		{
			return mid;
		}
		else if (L[mid] < ans)
			l++;
		else
			r--;
	}
	return r;
}

int main()
{
	long long tot = 0;

	cin >> n;

	for (long long i = 1; i <= n; i++)
		cin >> L[i];

	sort(L + 1, L + n + 1);

	for (long long i = 1; i <= n - 2; i++)
		for (long long j = i + 1; j <= n - 1; j++)
		{
			long long num = 0;
			long long pos = check(i, j);
			for (long long k = 1; k <= n; k++)
				if (L[pos] == L[pos + k])
					num++;
				else
					break;
			pos += num;
			tot += pos - j;
		}

	cout << tot << endl;

	return 0;
}

upper_bound版:代码又少,速度还快,我佛辣。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 2001

long long L[M];
long long n;

using namespace std;

int main()
{
	long long tot = 0;

	cin >> n;

	for (long long i = 1; i <= n; i++)
		cin >> L[i];

	sort(L + 1, L + n + 1);

	for (long long i = 1; i <= n - 2; i++)
		for (long long j = i + 1; j <= n - 1; j++)
		{
			long long tmp = L[i] + L[j] - 1;
			long long pos = upper_bound(L + j + 1, L + n + 1, tmp) - L;
			pos -= 1;
			tot += pos - j;
		}

	cout << tot << endl;

	return 0;
}

E. Travel by Car

考场上没时间想这道题了(虽然感觉有时间也想不出来)。题解的思路非常巧妙,如果要在路上加k次油,那么整条路径被加油点分为了k+1段,因此我们可以把每一段当成一个整体看待。具体的做法是先用Floyd求最短路,然后枚举所有路径,如果这条路径的长度小于等于L,就把它设置为1,如果大于就设置为Inf。然后再跑一遍Floyd,dis[from][to]-1就是加油的次数。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M 301
#define MA 1e9+1

using namespace std;

int dis[M][M];

int main()
{
	int n, m, l;
	
	cin >> n >> m >> l;

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			dis[i][j] = MA;

	for (int i = 1; i <= m; i++)
	{
		int from, to, cost;
		cin >> from >> to >> cost;
		dis[from][to] = dis[to][from] = cost;
	}

	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);

	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] <= l)
				dis[i][j] = 1;
			else
				dis[i][j] = MA;

	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);

	int q;
	cin >> q;
	for (int i = 1; i <= q; i++)
	{
		int from, to;
		cin >> from >> to;
		if (dis[from][to] == MA)
			cout << -1 << endl;
		else
			cout << dis[from][to] - 1 << endl;
	}

	return 0;
}

F. Distinct Numbers

给出一个长度为N的序列,求对于所有k∈[1,N] ,每次从序列中取出k个互不相同的数,最多能取多少次。
首先我们发现数字具体的数值是没有意义的,关键是其出现的次数,所以可以先用一个桶排序计数,然后把出现的次数排序得到数组a。假设取出k个数的操作数为x,那么一共会取出k*x个数。而理论上能取出的数量上限是:对于出现次数小于等于x的数,将其全部取出,对于出现次数大于x的数,每个取x个出来。显然k*x必定小于等于这个上限,我们要找的就是满足这个条件的最大的x,因此可以二分答案,即对于每个x,检查它是否满足这个条件,满足就放大,不满足就缩小。为了寻找a中小于等于x的数的总和,我们可以先求一个前缀和,再在a中二分查找它的位置,最后的复杂度是O(nlog2n)。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <map>

#define M (long long)3e5 + 10

using namespace std;

long long cnt[M], a[M], sum[M];

int main()
{
	long long n, tot = 0;

	cin >> n;

	for (long long i = 1; i <= n; i++)
	{
		long long tmp;
		cin >> tmp;
		cnt[tmp]++;
	}

	for (long long i = 1; i <= n; i++)
	{
		if (cnt[i] != 0)
			a[++tot] = cnt[i];
	}

	sort(a + 1, a + tot + 1);

	sum[1] = a[1];

	for (long long i = 2; i <= tot; i++)
		sum[i] = sum[i - 1] + a[i];								//前缀和

	for (long long k = 1; k <= n; k++)
	{
		long long l = 1, r = n;
		while (l <= r)
		{
			long long mid = (l + r) >> 1;
			long long pos = upper_bound(a + 1, a + tot + 1, mid) - a;		//返回数组中第一个大于或等于被查数的值的下标
			pos--;											//小于等于mid的数的个数

			if (sum[pos] + (tot - pos) * mid < k * mid)
				r = mid - 1;
			else
				l = mid + 1;
		}
		cout << r << endl;
	}

	return 0;
}

 

Add a Comment

Your email address will not be published. Required fields are marked *