\(\text{By hhoppitree.}\)
\(\textbf{Round 1 A. Apair}\)
題目大意
給定平面直角座標系上的 \(n\) 個整點,求任意兩個不同的點的曼哈頓距離與歐幾里得距離的比的最大值,多組詢問。
資料範圍:\(T\le10,n\le10^5\),\(\texttt{1s/512MB}\)。
思路分析
考慮我們就是要讓連線段的角度最接近 \(\dfrac{\pi}{4}\) 或 \(\dfrac{3\pi}{4}\),將平面直角座標系旋轉對應角度後也就是要求連線段與 \(x\) 軸夾角最小的兩個點。
按旋轉後的 \(y\) 座標排序後,最優解一定可以在兩個點相鄰的時候取到,證明可以畫畫圖。
最終的時間複雜度為單組詢問 \(\mathcal{O}(n\log n)\)。
程式碼呈現
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const long double pi = acos(-1.0);
int n;
pair<int, int> c[N];
int cmp1(pair<int, int> x, pair<int, int> y) {
return x.first + x.second < y.first + y.second;
}
int cmp2(pair<int, int> x, pair<int, int> y) {
return x.first - x.second < y.first - y.second;
}
long double calc() {
long double res = 0;
for (int i = 1; i < n; ++i) {
int x = abs(c[i].first - c[i + 1].first), y = abs(c[i].second - c[i + 1].second);
res = max(res, (x + y) / hypot((long double)x, (long double)y));
}
return res;
}
signed main() {
freopen("Apair.in", "r", stdin);
freopen("Apair.out", "w", stdout);
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d%d", &c[i].first, &c[i].second);
sort(c + 1, c + n + 1, cmp1);
long double res = calc();
sort(c + 1, c + n + 1, cmp2);
printf("%.20Lf\n", max(res, calc()));
}
return 0;
}
\(\textbf{Round 1 D. Dmagic}\)
題目大意
有兩個長度為 \(n\) 的陣列 \(a\) 和 \(b\),初始時 \(a\) 給定,\(b\) 均為 \(0\),每次可以選擇陣列 \(b\) 的字首或者是字尾加 \(1\),花費為選中元素個數,求最少花費使得 \(b_i\) 均不小於 \(a_i\),多組詢問。
資料範圍:\(T\le10,n\le10^5\),\(\texttt{1s/512MB}\)。
思路分析
考慮最終花費即為 \(b\) 陣列元素之和。
也就是說,我們要找到一個“可生成的”序列 \(b\),使得 \(b_i\ge a_i\),且在此基礎上,\(\sum_{i=1}^{n}b_i\) 最小。
不妨將 \(b\) 數列從初始全為 \(0\) 增加視作是一次操作將前字尾減 \(1\),求其是否能夠變成全 \(0\) 數列。
如何去刻畫一個序列“可被生成”呢?注意到,如果 \(b_i>b_{i+1}\),那麼至少要對 \([1,i]\) 進行 \(b_i-b_{i+1}\) 次字首操作;反之,如果 \(b_i<b_{i+1}\),那麼至少要對 \([i+1,n]\) 進行 \(b_{i+1}-b_i\) 次字尾操作。
在這些操作進行完後,必然有 \(b\) 中元素全相等,此時若有 \(b_i\ge 0\) 則序列 \(b\) 就是可以被生成的。
考慮用一個簡潔的式子去概括,不妨只考察 \(b_1\ge0\) 的限制,則有 \(b_1-\sum\limits_{i=1}^{n-1}\max(b_i-b_{i+1},0)\ge0\)