TAP
GYM 105321 N
题目描述
一个长宽高分别为 \(a,b,c\) 的代价为 \(ab+ac+bc\),价值为 \(a^2+b^2+c^2\),其收益为价值减代价。给定可选的长宽高 \(V_i\),求最大收益。
思路
直接拆式子:
\[\begin{array}{l}
a^2+b^2+c^2-ab-ac-bc\\
=\frac{1}{2}(a^2+a^2+b^2+b^2+c^2+c^2-2ab-2ac-2bc)\\
=\frac{1}{2}((a^2-2ab+b^2)+(a^2-2ac+c^2)+(b^2-2bc+c^2))\\
=\frac{1}{2}((a-b)^2+(a-c)^2+(b-c)^2)
\end{array}
\]
以上这个式子很明显 \(a\) 越大越好,\(c\) 越小越好,所以让 \(a,c\) 分别取最大值,最小值,并枚举 \(b\) 即可。
时空复杂度均为 \(O(N)\)。
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 5001;
int n, a[MAXN], Min = 1000001, Max;
ll ans;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
Min = min(Min, a[i]), Max = max(Max, a[i]);
}
for(int i = 1; i <= n; ++i) {
ans = max(ans, (1ll * (Min - a[i]) * (Min - a[i]) + 1ll * (Min - Max) * (Min - Max) + 1ll * (a[i] - Max) * (a[i] - Max)) / 2);
}
cout << ans;
return 0;
}
GYM 105321 H
题目描述
有 \(N\) 个矩形围栏,这些围栏没有点相交。有 \(M\) 个降落点,有两个人将等概率地落在这些降落点上。求它们要走到一起总共需要穿越围栏数的期望值。
思路
显然要穿过一个栅栏当且仅当一个人在栅栏里,另一个人在栅栏外。所以我们只需统计栅栏里的降落点数量并计算即可。也就是二维数点。
空间复杂度 \(O(N+M)\),时间复杂度 \(O((N+M)\log (N+M))\)。
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200001;
struct Node {
int x, y, x2, y2;
}a[MAXN];
struct node {
int x, y;
}b[MAXN];
int n, m, X[3 * MAXN], Y[3 * MAXN], tot, tot2, tr[3 * MAXN], ans[MAXN];
ll Ans;
vector<tuple<int, int, int, int>> ve[3 * MAXN];
vector<int> vec[3 * MAXN];
int lowbit(int x) {
return x & -x;
}
void update(int p, int x) {
for(; p <= 2 * n + m; tr[p] += x, p += lowbit(p)) {
}
}
int Getsum(int p) {
int sum = 0;
for(; p; sum += tr[p], p -= lowbit(p)) {
}
return sum;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
cin >> a[i].x >> a[i].y >> a[i].x2 >> a[i].y2;
X[i] = a[i].x, X[n + i] = a[i].x2;
Y[i] = a[i].y, Y[n + i] = a[i].y2;
}
for(int i = 1; i <= m; ++i) {
cin >> b[i].x >> b[i].y;
X[2 * n + i] = b[i].x, Y[2 * n + i] = b[i].y;
}
sort(X + 1, X + 2 * n + m + 1);
sort(Y + 1, Y + 2 * n + m + 1);
for(int i = 1; i <= 2 * n + m; ++i) {
if(!tot || X[i] > X[tot]) {
X[++tot] = X[i];
}
}
for(int i = 1; i <= 2 * n + m; ++i) {
if(!tot2 || Y[i] > Y[tot2]) {
Y[++tot2]= Y[i];
}
}
for(int i = 1; i <= n; ++i) {
a[i].x = lower_bound(X + 1, X + tot + 1, a[i].x) - X;
a[i].x2 = lower_bound(X + 1, X + tot + 1, a[i].x2) - X;
a[i].y = lower_bound(Y + 1, Y + tot2 + 1, a[i].y) - Y;
a[i].y2 = lower_bound(Y + 1, Y + tot2 + 1, a[i].y2) - Y;
ve[a[i].x - 1].emplace_back(a[i].y, a[i].y2, -1, i);
ve[a[i].x2].emplace_back(a[i].y, a[i].y2, 1, i);
}
for(int i = 1; i <= m; ++i) {
b[i].x = lower_bound(X + 1, X + tot + 1, b[i].x) - X;
b[i].y = lower_bound(Y + 1, Y + tot2 + 1, b[i].y) - Y;
vec[b[i].x].push_back(b[i].y);
}
for(int i = 1; i <= 2 * n + m; ++i) {
for(int x : vec[i]) {
update(x, 1);
}
for(auto [l, r, x, id] : ve[i]) {
ans[id] += x * (Getsum(r) - Getsum(l - 1));
}
}
for(int i = 1; i <= n; ++i) {
Ans += 2ll * ans[i] * (m - ans[i]);
}
cout << fixed << setprecision(9) << 1.0l * Ans / (1.0l * m * m);
return 0;
}