(2024)第五届辽宁省大学生程序设计竞赛 (大连)

A. 爱上字典

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;
using ui32 = unsigned int;

using vi = vector<int>;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	string s, t = "";
	getline(cin, s);
	s += ' ';

	set<string> cnt;
	for(int i = 0; i < s.size(); i ++) {
		if(s[i] >= 'a' and s[i] <= 'z')
			t += s[i];
		else if(s[i] >= 'A' and s[i] <= 'Z')
			t += s[i] - 'A' + 'a';
		else {
			if(t.empty()) continue;
			cnt.insert(t);
			t = "";
		}
	}

	int n;
	cin >> n;
	for(; n; n --) {
		cin >> s;
		for(auto &c : s){
			if(c >= 'A' and c <= 'Z') c = c - 'A' + 'a';
		}
		cnt.erase(s);
	}
	cout << cnt.size() << "\n";


	return 0;
}

B. 比分幻术

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;
using ui32 = unsigned int;

using vi = vector<int>;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	string s;
	cin >> s;
	swap(s[0], s[2]);
	cout << s;
	return 0;
}

C. 插排串联

首先可以用dfs,求出所有节点的功率,然后贪心的给功率大的节点分配大的功率即可。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;
using ui32 = unsigned int;

#define int i64

using vi = vector<int>;
using pii = pair<int,int>;


i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	int n;
	cin >> n;
	
	vi W(n + 1);
	W[0] = -1;
	vi b, node;

	vector<vi> e(n + 1);

	for(int i = 1, f; i <= n; i ++) {
		cin >> f >> W[i];
		e[f].push_back(i);
		if(W[f] != -1) 
			b.push_back(W[f]), W[f] = -1, node.push_back(f);
	}

	auto dfs = [&](auto self, int x) -> void {
		if(W[x] != -1) return;
		W[x] = 0;
		for(auto y : e[x]) {
			self(self, y);
			W[x] += W[y];
		}
		return;
	};

	dfs(dfs, 0);

	if(W[0] > 2200) {
		cout << "NO\n";
		return 0;
	}
	ranges::sort(b);
	ranges::sort(node ,[&](const int &x, const int &y) -> bool {
		return W[x] < W[y];
	});

	for(int i = 0; i < b.size(); i ++) {
		if(b[i] >= W[node[i]]) continue;
		cout << "NO\n";
		return 0;
	}
	cout << "YES\n";
	return 0;
}

D. 都市叠高

看似求凸包,直径一定是一组点对,因此直接 dp 就好。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;
using ui32 = unsigned int;
using ldb = long double;

#define int i64

using vi = vector<int>;
using pii = pair<int,int>;


i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	int n;
	cin >> n;

	vector<ldb> x(n + 1), y(n + 1);
	for(int i = 1, _x, _y; i <= n; i++) 
		cin >> _x >> _y, x[i] = _x, y[i] = _y;

	vector<ldb> f(n + 1);
	for(int i = 1; i <= n; i ++) {
		f[i] = f[i - 1];
		ldb maxx = 0;
		for(int j = i - 1; j >= 1; j --){
			maxx = max(maxx, hypot(x[i] - x[j], y[i] - y[j]));
			f[i] = max(f[i], f[j - 1] + maxx);
		}
	}
	cout << fixed << setprecision(20) << f[n] << "\n";
	return 0;
}

E. 俄式简餐

能够拼出来的基础方形有\(1\times 4,2\times 6\),两种。

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;
using ui32 = unsigned int;

using vi = vector<int>;

void solve(){
	int n, m, k = 0;
	cin >> n >> m;

	if((n * m) % 4 != 0) {
		cout << "NO\n";
		return;
	}

	if(n == 2 and m == 2) {
		cout << "NO\n";
		return;
	}

	vector g(n + 1, vi(m + 1));

	if(n % 4 == 0){
		for(int j = 1; j <= m; j ++)
			for(int i = 1; i <= n; i += 4) {
				k ++;
				g[i][j] = g[i + 1][j] = g[i + 2][j] = g[i + 3][j] = k;
			}
	} else if(m % 4 == 0) {
		for(int i = 1; i <= n; i ++) 
			for(int j = 1; j <= m; j += 4) {
				k ++;
				g[i][j] = g[i][j + 1] = g[i][j + 2] = g[i][j + 3] = k;
			}
	} else if(m > 2) {
		for(int i = 1; i <= n; i += 2) {
			k ++;
			g[i][1] = g[i][2] = g[i][3] = g[i + 1][1] = k;
			k ++;
			g[i][4] = g[i][5] = g[i][6] = g[i + 1][6] = k;
			k ++;
			g[i + 1][2] = g[i + 1][3] = g[i + 1][4] = g[i + 1][5] = k; 
			for(int j = 7; j <= m; j += 4) {
				k ++;
				g[i][j] = g[i][j + 1] = g[i][j + 2] = g[i][j + 3] = k;
				k ++;
				g[i + 1][j] = g[i + 1][j + 1] = g[i + 1][j + 2] = g[i + 1][j + 3] = k;
			}
		}
	} else if(n > 2){
		for(int j = 1; j <= m; j += 2) {
			k ++;
			g[1][j] = g[2][j] = g[3][j] = g[1][j + 1] = k;
			k ++;
			g[4][j] = g[5][j] = g[6][j] = g[6][j + 1] = k;
			k ++;
			g[2][j + 1] = g[3][j + 1] = g[4][j + 1] = g[5][j + 1] = k;
			for(int i = 7; i <= n; i += 4) {
				k ++;
				g[i][j] = g[i + 1][j] = g[i + 2][j] = g[i + 3][j] = k;
				k ++;
				g[i][j + 1] = g[i + 1][j + 1] = g[i + 2][j + 1] = g[i + 3][j + 1] = k;
			}
		}
	}

	cout << "YES\n";
	for(int i = 1; i <= n; i ++){
		for(int j = 1; j <= m; j ++) {
			cout << g[i][j] << " ";
		}
		cout << "\n";
	}
	return ;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);

	int t;

	std::cin >> t;

	while (t--){
		solve();
	}

	return 0;
}

G. 顾影自怜

我们可以枚举每一个数\(a_i\),作为第一个最大值出现。为了计算答案,我们要预处理\(L[i]\)表示\(i\)左侧第一个比\(a_i\)大的数的下标,\(R[i]\)表示\(i\)右侧第一个比\(a_i\)大的数的下标。\(lst[i]\)表示\(i\)第一个\(a_i\)出现的下标,\(nxt[i]\)表示\(i\)后第\(k\)\(a_i\)出现的位置。

\(a_i\)作为第一个最大值的合法左端点的范围是\((\min(lst[i], L[i]), i]\),右端点的范围是\([nxt[i],R[i])\)

\(L[i],R[i]\)用单调栈统计,\(lst[i],nxt[i]\)用值域桶统计,总体复杂度\(O(N)\)

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;
using ui32 = unsigned int;

#define int i64

using vi = vector<int>;

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

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

	for(int i = 1; i <= n; i ++)
		assert( 1 <= a[i] and a[i] <= n);

	vector vis(n + 1, vi(1, 0));

	for(int i = 1;i <= n; i ++)
		vis[a[i]].push_back(i);


	vi lst(n + 1), nxt(n + 1, -1);
	for(int i = 1; i <= n; i ++) {
		if(vis[i].size() - 1 < k) continue;
		for(int l = 1, r = k; r < vis[i].size(); l ++, r ++) {
			lst[vis[i][l]] = vis[i][l - 1];
			nxt[vis[i][l]] = vis[i][r];

		}
	}
	
	vi L(n + 1);
	stack<int> stk;
	for(int i = 1; i <= n; i ++) {
		while(not stk.empty() and a[stk.top()] <= a[i])
			stk.pop();
		if(stk.empty()) L[i] = 0;
		else L[i] = stk.top();
		stk.push(i); 
	}

	vi R(n + 1);
	stk = stack<int>();
	for(int i = n; i >= 1; i --) {
		while(not stk.empty() and a[stk.top()] <= a[i])
			stk.pop();
		if(stk.empty()) R[i] = n + 1;
		else R[i] = stk.top();
		stk.push(i);
	}
	int res = 0;
	for(int i = 1; i <= n; i ++){
		if(nxt[i] == -1) continue;
		int l = i - max(lst[i], L[i]);
		int r = R[i] - nxt[i];
		if(l < 0 or r < 0) continue;
		res += l * r;
	}
	cout << res << "\n";
	return ;
}

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	int T;
	cin >> T;
	while(T --)
		solve();

	return 0;
}

J. 结课风云

签到

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;
using ui32 = unsigned int;

using vi = vector<int>;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	int n;
	cin >> n;

	int a, b, c;
	cin >> a >> b >> c;

	vi x(n), y(n);

	for(int i = 0 ; i < n; i ++)
		cin >> x[i] >> y[i];

	int ret = 0;
	for(int i = 0; i < n; i ++)
		ret +=  (x[i] + y[i]) < c;

	int d;
	cin >> d;

	for(int i = 0; i < n; i ++) 
		x[i] = min(x[i] + d, a);
	
	int res = 0;
	for(int i = 0; i < n; i ++)
		res +=  (x[i] + y[i]) < c;

	cout << ret - res;


	return 0;
}

L. 龙之研习

可以发现,不会有任何一个数同时满足两个及以上条件。因此就变成了简单的容斥。

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;
using ui32 = unsigned int;

#define int i64

using vi = vector<int>;

int base = 0;
vi p1, p2;

void init() {
	p1.push_back(4), p2.push_back(100);
	while(p2.back() != 1e18) {
		p1.push_back(p1.back() * 100);
		p2.push_back(p2.back() * 100);
	}
}

int calc(int x) {
	int y = x;
	for(int i = 0; i < p1.size(); i ++)
		y = y - (x / p1[i]) + (x / p2[i]);
	return y;
}

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

	int l = 1, r = 2e18, ret = -1;
	while(l <= r) {
		int mid = (l + r) / 2;

		int cnt = calc(mid);

		if(cnt - base >= k) ret = mid, r = mid - 1;
		else l = mid + 1;
	}

	cout << ret << "\n";
	return;
}


i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	init();
	base = calc(2024);

	int T;
	cin >> T;
	while(T --)
		solve();

	return 0;
}

M. 盲盒谜题

模拟题,这里把放和删操作做了一个封装。

有一个注意点是,只要被放了,最后就一定会拿到,因此可以在放的过程中直接统计拿了多少。

#include <bits/stdc++.h>

using namespace std;


using i64 = long long;
using ui32 = unsigned int;

using vi = vector<int>;
using pii = pair<int,int>;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);

	int have, m, k, lucky, used = 0;
	cin >> have >> m >> k >> lucky;
	vector<int> a(k + 1);
	for(int i = 1; i <= k; i ++)
		cin >> a[i];

	bool ok = true;
	vi cnt(m + 1); // 统计个数
	vector g(3, vi(3, -1)); // 记录图
	vector<pii> pos = {{1,1}, {0,0}, {0,1}, {0,2}, {1,0}, {1,2}, {2,0}, {2,1}, {2,2}};
	vector<array<int,3>> step3_line = {	{0, 1, 8},	{0, 2, 7},	{0, 3, 6},
										{0, 4, 5},	{1, 2, 3},	{1, 4, 6},
										{3, 5, 8}, 	{6, 7, 8}};	

	auto solve = [&]() -> void {
		bool opted = false, delSpecial = false;

		auto val = [&](int i) -> int{
			const auto &[x, y] = pos[i];
			return g[x][y];
		};

		auto add = [&](int i) -> void {
			const auto &[x, y] = pos[i];
			opted = true;
			have --;
			used ++;
			cnt[a[used]] ++;
			g[x][y] = a[used];
			if(a[used] == 0) {
				have ++;
				g[x][y] = -1;
			} else if(a[used] == lucky) {
				have ++;
			}
			return;
		};

		auto del = [&](int i, bool special = false) -> void {
			if(i == 0 and special == false) {
				delSpecial = true;
				return;
			}
			const auto &[x, y] = pos[i];
			opted = true;
			g[x][y] = -1;
			return;
		};

		// step 1
		for(int i = 0; i < 9; i ++) 
			while(val(i) == -1 and have > 0 and used < k)
				add(i);

		// step 2
		set<int> cntStep2;
		for(auto [x, y] : pos)
			cntStep2.insert(g[x][y]);
		if(cntStep2.size() == 9 and cntStep2.count(-1) == 0){
			del(0, true);
			return;
		}	

		// step 3
		for(const auto &[x, y, z] : step3_line) {
			if(val(x) == -1) continue;
			if(val(x) != val(y) or val(x) != val(z)) continue;
			del(x), del(y), del(z);
			have += 5; // 奖励
		}

		// step 4
		for(int i = 0; i < 9; i ++ ) {
			if(val(i) == -1) continue;
			for(int j = i + 1; j < 9 and val(i) != -1 ; j ++) {
				if(val(i) != val(j)) continue;
				del(i), del(j);
				have ++;
			}
		}

		// step 5
		del(0, delSpecial);

		// step 6
		if(opted == false){
			ok = false;
			return;
		}
		set<int> cntStep6;
		for(auto [x, y] : pos) 
			cntStep6.insert(g[x][y]);
		if(cntStep6.size() == 1 and *cntStep6.begin() == -1)
			have += 10;
		return;
	};

	while(ok)
		solve();

	for(auto i : cnt)
		cout << i << " ";
	cout << "\n";
	if(have > 0) cout << "Unhappy! " << have << "\n";
	return 0;
}

posted @ 2024-11-06 21:34  PHarr  阅读(59)  评论(0编辑  收藏  举报