第21届UESTCPC题解(AEFIJK)(赛时3题)

题目链接

赛时糖丸了,一开始看到K然后想到假做法被卡飞,J也因为题意各种绕和我自己各种绕把自己绕似了,被活活打断了双腿

A 调整法

注意到每一个字符串对逆序对的贡献在于自己的逆序对加上自己的0乘以左边的1加上自己的1乘以右边的0——它和某个具体的串的位置无关,只与每两个串的相对位置有关,故调整法排序即可

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

template<class T, class F> concept binary_func = convertible_to<F, function<bool(T, T)>>;
template<class T1, class T2, class F> requires(binary_func<T1, F> &&convertible_to<T2, T1>) bool chkf(T1 &x, const T2 &y, F &&f) {
	if(f(static_cast<T1>(y), x)) {
		x = static_cast<T1>(y);
		return true;
	}
	return false;
}
template<class T1, class T2> bool chkmin(T1 &x, const T2 &y) {
	return chkf(x, y, less<T1>{});
}
template<class T1, class T2> bool chkmax(T1 &x, const T2 &y) {
	return chkf(x, y, greater<T1>{});
}

struct Str {
	string data;
	ll cnt0, cnt1;
	friend istream &operator>>(istream &is, Str &self) {
		is >> self.data;
		for(char c : self.data) {
			if(c == '0') ++self.cnt0;
			else ++self.cnt1;
		}
		return is;
	}
	bool operator<(const Str &s) const {
		ll self_prio = cnt1 * s.cnt0, s_prio = s.cnt1 * cnt0;
		return self_prio < s_prio;
	}
};

inline void solve() {
	int n;
	cin >> n;
	vector<Str> strs(n);
	for(int i = 0; i < n; ++i) {
		cin >> strs[i];
	}
	sort(strs.begin(), strs.end());
	string ret;
	for(auto &s : strs) {
		ret += s.data;
	}
	ll ans = 0, cnt1 = 0;
	for(char c : ret) {
		if(c == '0') {
			ans += cnt1;
		} else {
			++cnt1;
		}
	}
	cout << ans << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	// cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}

C 相对位移+切线

上把ABC才做了个相对位移,这把看到题想到了,画图时忘了,我是傻13

首先转化为相对位移,然后圆相交转化为点和大圆(半径为两个圆的和)相交,然后造切线草即可

// 写3小时破防下播了,马上补

E 模拟

模拟还有什么可说的,草呗

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

template<class T, class F> concept binary_func = convertible_to<F, function<bool(T, T)>>;
template<class T1, class T2, class F> requires(binary_func<T1, F> &&convertible_to<T2, T1>) bool chkf(T1 &x, const T2 &y, F &&f) {
	if(f(static_cast<T1>(y), x)) {
		x = static_cast<T1>(y);
		return true;
	}
	return false;
}
template<class T1, class T2> bool chkmin(T1 &x, const T2 &y) {
	return chkf(x, y, less<T1>{});
}
template<class T1, class T2> bool chkmax(T1 &x, const T2 &y) {
	return chkf(x, y, greater<T1>{});
}

inline void solve() {
	int tot_cre, tot_cou_cre, compul, degree, pro_cou, pro_fund_cou, pro_elec_cou;
	cin >> tot_cre >> tot_cou_cre >> compul >> degree >> pro_cou >> pro_fund_cou >> pro_elec_cou;
	bool pub_fund_taken = false;
	int n;
	cin >> n;
	while(n--) {
		cin.ignore();
		string s;
		getline(cin, s);
		getline(cin, s);
		int score;
		cin >> score;
		tot_cre -= score;
		if(s == "public foundational courses") {
			tot_cou_cre -= score;
			degree -= score;
			pub_fund_taken = true;
		} else if(s == "professional foundational courses") {
			tot_cou_cre -= score;
			degree -= score;
			pro_cou -= score;
			pro_fund_cou -= score;
		} else if(s == "professional elective courses") {
			tot_cou_cre -= score;
			pro_cou -= score;
			pro_elec_cou -= score;
		} else if(s == "interdisciplinary elective courses") {
			tot_cou_cre -= score;
		} else if(s == "other elective courses") {
			tot_cou_cre -= score;
		} else {
			compul -= score;
		}
	}
	if(tot_cre <= 0 && tot_cou_cre <= 0 && compul <= 0 && degree <= 0 && pro_cou <= 0 && pro_fund_cou <= 0 && pro_elec_cou <= 0 && pub_fund_taken) {
		cout << "YES\n";
	} else {
		cout << "NO\n";
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}

F 随机化

题解说的啥不知道,和我的随机化说去吧

每个数在这个区间的概率至少一半,则我们每选一个数就有一半的概率在区间里面,这样我们随机选100个数,有高达 \(2^{-100}\) 的概率有0个数在区间里,其余时候至少有1个数在区间里,第二次读的时候每个数记录它加减k的区间有几个数然后统计最大值即可

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

template<class T, class F> concept binary_func = convertible_to<F, function<bool(T, T)>>;
template<class T1, class T2, class F> requires(binary_func<T1, F> &&convertible_to<T2, T1>) bool chkf(T1 &x, const T2 &y, F &&f) {
	if(f(static_cast<T1>(y), x)) {
		x = static_cast<T1>(y);
		return true;
	}
	return false;
}
template<class T1, class T2> bool chkmin(T1 &x, const T2 &y) {
	return chkf(x, y, less<T1>{});
}
template<class T1, class T2> bool chkmax(T1 &x, const T2 &y) {
	return chkf(x, y, greater<T1>{});
}

inline void solve() {
	int n, k;
	cin >> n >> k;
	mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());
	uniform_int_distribution<int> unif(0, n - 1);
	int indecies[100];
	for(int i = 0; i < 100; ++i) {
		indecies[i] = unif(rng);
	}
	sort(indecies, indecies + 100);
	fill(unique(indecies, indecies + 100), indecies + 100, n + 20);
	int now = 0;
	vector<int> targets;
	for(int i = 0; i < n; ++i) {
		int u;
		cin >> u;
		if(i == indecies[now]) {
			++now;
			targets.push_back(u);
		}
	}
	vector<vector<int>> cnter(now, vector<int>(2 * k + 1));
	for(int i = 0; i < n; ++i) {
		int u;
		cin >> u;
		for(int d = 0; d < now; ++d) {
			int id = targets[d] - u + k;
			if(id >= 0 && id <= 2 * k) {
				cnter[d][id]++;
			}
		}
	}
	int ans = 0;
	for(int i = 0; i < now; ++i) {
		vector<int> pre(2 * k + 2, 0);
		for(int j = 0; j < 2 * k + 1; ++j) {
			pre[j + 1] = pre[j] + cnter[i][j];
		}
		for(int j = k + 1; j <= 2 * k + 1; ++j) {
			chkmax(ans, pre[j] - pre[j - k - 1]);
		}
	}
	cout << ans << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	// cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}

I 看数据范围

孩子们,这是力扣的原,看到 \(n\cdot c\le 10^7\) 直接模拟就过了

// 赛时没看到n*c<=1e7,我是傻逼
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

inline void solve() {
	string s;
	cin >> s;
	int m = s.size();
	int n;
	cin >> n;
	vector<int> nums(n);
	for(int i = 0; i < n; ++i) {
		cin >> nums[i];
	}
	for(int i = n - 1; i >= 0; --i) {
		if(nums[i] == 1) continue;
		vector<vector<int>> at(nums[i]);
		bool inc = true;
		int now = 1;
		at[0].push_back(0);
		for(int j = 1; j < m; ++j) {
			if(now == 0 || now == nums[i] - 1) inc = !inc;
			at[now].push_back(j);
			inc ? (++now) : (--now);
		}
		vector<int> rev;
		rev.reserve(m);
		for(int j = 0; j < nums[i]; ++j) {
			for(int u : at[j]) {
				rev.push_back(u);
			}
		}
		string t(m, '?');
		for(int j = 0; j < m; ++j) {
			t[rev[j]] = s[j];
		}
		s = t;
	}
	cout << s << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	// cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}

J 读题+贪心+细心

我还能说什么呢?

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;

inline void solve() {
	int n;
	cin >> n;
	vector<pair<int, int>> songs(n);
	vector<int> rev(n);
	for(int i = 0; i < n; ++i) {
		cin >> songs[i].first >> songs[i].second;
		--songs[i].second;
		rev[songs[i].second] = i;
	}
	vector<int> low, high;
	set<int> s;
	for(int i = 0; i < n; ++i) {
		s.insert(i);
	}
	vector<int> ans(n, -1);
	for(int i = 0; i < n; ++i) {
		if(songs[i].first == 0) {
			s.erase(songs[i].second);
			ans[i] = songs[i].second;
		} else if(songs[i].first == -1) {
			low.push_back(songs[i].second);
		} else {
			high.push_back(songs[i].second);
		}
	}
	sort(low.begin(), low.end());
	sort(high.begin(), high.end(), greater());
	for(int i : low) {
		int dst = *s.begin();
		if(dst >= i) {
			cout << "-1\n";
			return;
		}
		ans[rev[i]] = dst;
		s.erase(dst);
	}
	for(int i : high) {
		int dst = *s.rbegin();
		if(dst <= i) {
			cout << "-1\n";
			return;
		}
		ans[rev[i]] = dst;
		s.erase(dst);
	}
	vector<int> ret(n);
	for(int i = 0; i < n; ++i) {
		// CRITICAL FIX by Gemini
		ret[ans[i]] = songs[i].second; // 这里我赛时打成rev[i]了,警示后人
	}
	for(int i : ret) {
		cout << (i + 1) << ' ';
	}
	cout << '\n';
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}

K 构造

有个彩笔琪厨这题没过,水群的时候喊琪1的底气都没那么足了,望周知

喜报:Gemini的做法会被自己用来hack我的数据hack掉

注意到如果长方体为 \(a\cdot b\cdot c\) ,且 \(a\le b\le c\) ,则可以将它用一刀切成 \(a\cdot (b-a)\cdot c\)\(a\cdot b\cdot (c-b)\) ,据此,如果 \(\frac{b}{a}\) 较小按照方案一切,否则按方案二切,切完之后就是更小的问题,注意退出条件即可

我不知道我自己写的时候为什么会有那么多神秘bug,调来调去,看GPT给的东西和我自己的也没什么区别,但我的就是WA,GPT的就是AC,人麻了

#include <bits/stdc++.h>
using namespace std;
 
using ll = long long;
using ull = unsigned long long;
using ld = long double;
 
struct Point {
	array<ll, 3> c;
	Point() : c({}) {}
	Point(ll x, ll y, ll z) : c({x, y, z}) {}
	Point operator+(const Point &p) const {return Point(c[0] + p.c[0], c[1] + p.c[1], c[2] + p.c[2]);}
	Point operator-(const Point &p) const {return Point(c[0] - p.c[0], c[1] - p.c[1], c[2] - p.c[2]);}
	bool operator==(const Point &) const = default;
};
 
inline void solve() {
	Point dst;
	cin >> dst.c[0] >> dst.c[1] >> dst.c[2];
	Point now;
	constexpr ll THRE = 31415;
	vector<array<ll, 6>> ans;
	auto minmedmax = [&](const array<ll, 3> &arr) {
		array<int, 3> idx = { 0,1,2 };
		sort(idx.begin(), idx.end(), [&](int i, int j) {
			return arr[i] < arr[j];
		});
		array<ll, 3> val = { arr[idx[0]], arr[idx[1]], arr[idx[2]] };
		return pair{ idx, val };
	};
	while(now != dst) {
		array<ll, 3> rem = { dst.c[0] - now.c[0], dst.c[1] - now.c[1], dst.c[2] - now.c[2] };
		auto [idx, val] = minmedmax(rem);
		array<ll, 6> op{};
		op[0] = now.c[0]; op[1] = now.c[1]; op[2] = now.c[2];
		if(val[1] > THRE) {
			for(int i = 0; i < 3; i++) {
				ll len = (i == 0 ? val[0] : val[1]);
				op[idx[i] + 3] = now.c[idx[i]] + len;
			}
			ans.push_back(op);
			if(op[3] == dst.c[0] && op[4] == dst.c[1] && op[5] == dst.c[2]) break;
			now.c[idx[2]] += val[1];
		} else {
			for(int i = 0; i < 3; i++) {
				ll len = (i == 2 ? val[2] : val[0]);
				op[idx[i] + 3] = now.c[idx[i]] + len;
			}
			ans.push_back(op);
			if(op[3] == dst.c[0] && op[4] == dst.c[1] && op[5] == dst.c[2]) break;
			now.c[idx[1]] += val[0];
		}
	}
	cout << ans.size() << '\n';
	for(auto [a, b, c, d, e, f] : ans) {
		cout << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << ' ' << f << '\n';
	}
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	int n = 1;
	// cin >> n;
	while(n--) {
		solve();
	}
	return 0;
}
posted @ 2025-09-04 00:40  氧烷OH2  阅读(12)  评论(0)    收藏  举报