The 3rd Universal Cup. Stage 12: Qinhuangdao

A. Balloon Robot

首先我们可以把时间和坐标都映射为从0 开始的。

然后对于一个事件\((a,b)\),实际上和\((a-1,b-1)\)是等价的。因此我们可以把所有的事件都放到位置\(0\)上发生。

这样做有什么好处?发气球从每秒都可以发变成了,每\(m\)秒发一批。这样我们就可以枚举第一次发气球的时间,并用前缀和快速的计算出其他事件等待的时间。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;
const int inf = LLONG_MAX / 2;

void solve() {
	int n, m, p;
	cin >> n >> m >> p;

	vi s(n);
	for(auto &i : s) 
		cin >> i, i --;

	map<int,int> cnt;
	for(int a, b; p; p --) {
		cin >> a >> b, a --;
		a = s[a] , b --;
		b = (b - a + m) % m;
		cnt[b] ++;
	}
	
	vi val(1), num(1);
	for(auto [x, y] : cnt){
		val.push_back(x);
		num.push_back(y);
	}

	int N = val.size() - 1;

	vi preVal(N + 1), preNum(N + 1);
	
	for(int i = 1; i <= N; i ++) {
		preVal[i] = preVal[i - 1] + val[i] * num[i];
		preNum[i] = preNum[i - 1] + num[i];
	}

	int res = inf;
	for(int i = 1 , ret; i <= N; i ++) {
		ret = 0;
		if(i - 1 >= 1) ret += val[i] * preNum[i - 1] - preVal[i - 1];
		if(i + 1 <= N) ret += (val[i] + m) * (preNum[N] - preNum[i]) - (preVal[N] - preVal[i]);
		res = min(res, ret);
	} 
	cout << res << "\n";
	return;
}

i32 main() {
	int T;
	cin >> T;
	
	while(T --)
		solve();
	return 0;
}

C. Crusaders Quest

这个题目数据范围很小直接暴力枚举就好了。

#include <bits/stdc++.h>

using namespace std;


const string tmp = "gao";

void solve() {
	string s;
	cin >> s;
	int res = 0;

	auto dfs = [&res](auto &&self, string s, int cnt) -> void {
		res = max(res, cnt);
		
		if(s.size() < 3){
			return;
		}

		for(int i = 0, j; i < s.size(); i ++) {
			j = i;
			while(j < s.size() and s[i] == s[j]) j ++;
			string t = s;
			t.erase(i, j - i);
			self(self, t, cnt + (i + 3 == j));
		}
		return;
	};

	dfs(dfs, s, 0);
	
	cout << res << "\n";
	return;
}

int main() {
	int T;
	cin >> T;
	
	while(T --)
		solve();
	return 0;
}

E. String of CCPC

可以发现,增加两个及以上的字母一定不是最优解。因此至多只会增加一个字母。

考虑增加字母的情况,当且仅当出现CPCCCCCCP三种情况。

但是要注意CCC可能会出现这种情况CCCPC,此时如果在第二个C后面增加一个P,就会变成CCPCPC,并不会更优,因此要特判去掉这种情况。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;
const int inf = LLONG_MAX / 2;

void solve() {
	int n;
	cin >> n;

	string s;
	cin >> s;

	int res = 0, f = 0;

	for(int i = 0; i < n; i ++) {
		if(s.substr(i, 4) == "CCPC") {
			res ++;
			i += 2;
		} else if(f == 0) {
			if(s.substr(i, 3) == "CPC") {
				res ++, f = 1;
			} else if(s.substr(i, 3) == "CCP") {
				res ++, f = 1;
			} else if(s.substr(i, 3) == "CCC" and s.substr(i + 1, 4) != "CCPC") {
				res ++, f = 1;
			}
		} 
	}
	cout << res << "\n";
}

i32 main() {
	int T;
	cin >> T;
	
	while(T --)
		solve();
	return 0;
}

G. Numbers

我们可以贪心的放置数字。我们从高位到低位逐位考虑。

对于第\(x\)位,如果第\(x-1\)都放满已经有剩余,也就是\((2^x-1)\times m < n\),则\(x\)就必须要放。如果\(x\)需要放置,则尽可能的放满。

实现需要高精度,可以用 Python 实现。

def log2(x):
	ret = 0
	while x > 1:
		ret += 1
		x //= 2
	return ret

def solve():
	n, m = map(int,input().split(' '))
	res = 0
	
	x = 2 ** int(log2(n) + 1)
	
	while n > 0:
		if (x - 1) * m < n :
			res += x
			n -= min(n //x, m) * x
		x //= 2

	print(res)

T = int(input())
for _ in range(T) :
	solve()

L. One-Dimensional Maze

如果从一个点向左走就必须全部L,如果一个点向右走就全部是R。计算一下需要修改的个数即可。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;
const int inf = LLONG_MAX / 2;

void solve() {
	int n, m;
	cin >> n >> m, m --;

	string s;
	cin >> s;

	int res = 0;
	for(int i = m; i < n - 1; i ++) 
		res += (s[i] == 'L');

	int ret = 0;
	for(int i = m; i > 0; i --)
		ret += (s[i] == 'R');

	cout << min(res, ret) << "\n";
	return;
}

i32 main() {
	int T;
	cin >> T;
	
	while(T --)
		solve();
	return 0;
}

M. Safest Buildings

距离圆心距离小于\(|R - 2r|\)的点肯定更优,除此之外离圆心越近的点越优。

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;

const i64 inf = LLONG_MAX / 2;

void solve() {
	int n, R, r;
	cin >> n >> R >> r;

	i64 val = inf, d = (2ll * r - R) * (2ll * r - R);
	vector<int> ret, res;


	for(int i = 1; i <= n; i ++) {
		i64 x, y, dis;
		cin >> x >> y;
		dis = x * x + y * y;
		
		if(dis < val) {
			val = dis, ret = vector<int>(1, i);
		} else if(dis == val) {
			ret.push_back(i);
		}

		if(dis <= d) {
			res.push_back(i);
		}

	}
	
	if(not res.empty()) {
		cout << res.size() << "\n";
		for(auto i : res)
			cout << i << " \n"[i == res.back()];
		return;
	}

	cout << ret.size() << "\n";
	for(auto i : ret)
		cout << i << " \n"[i == ret.back()];
	return;
}


int main() {
	int T;
	cin >> T;

	while(T --) 
		solve();

	return 0;
}
posted @ 2024-10-31 15:11  PHarr  阅读(29)  评论(0编辑  收藏  举报