第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;
}

浙公网安备 33010602011771号