[CF981F] 二分答案 貪心 校內集訓 8-2 T2
阿新 • • 發佈:2018-12-24
題目傳送門
感謝的講解!!
這是一道很棒的題~~ 模型轉化也比較需要思考
首先這個題可能會無從下手,仔細觀察可以發現一個性質,那就是一段新郎一定對應一段連續的新娘,可以用簡單證明下,如果存在一個匹配,有一個新郎跨越了另一個新郎的話,那麼這肯定不會最優,因為我們可以交換這兩個新郎所對應的新娘,使其多出來的一段距離消去,一定會讓答案更優。有了這個性質之後我們考慮二分答案,把新娘的序列擴充套件成三倍,分別代表從左往右跨越起點,從右往左跨越起點和不跨越起點三種情況,把兩個序列排序,首先找到第一個新郎能到達的新娘的區間,由於新郎必須連續對應一段新娘,那麼下一個新郎能到達的新娘的區間就是 與自己原本能到達區間的交集, 這樣如果存在一個新郎沒有選擇的區間那麼當前答案就是不可行的,否則就是可行的,這樣就做完了,複雜度
Codes
#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define mid ((l + r) >> 1)
using namespace std;
const int maxn = 6e5 + 10, mod = 20000909;
int n, L, a[maxn], b[maxn];
bool check(int x) {
int l = 1, r = n * 3;
For(i, 1, n) {
while(a[i] - b[l] > x)
++ l;
while(b[r] - a[i] > x)
-- r;
++ l, ++ r;
}
return l <= r;
}
void File() {
freopen("queue.in", "r", stdin);
freopen("queue.out", "w", stdout);
}
void Init() {
scanf("%d%d", &n, &L);
For(i, 1, n) scanf("%d", &a[i]);
For(i, 1, n) {
scanf("%d", &b[i]);
b[i + n] = b[i] + L;
b[i + 2 * n] = b[i] - L;
}
sort(a + 1, a + n + 1);
sort(b + 1, b + n * 3 + 1);
}
void Solve() {
int l = 0, r = L + 1 >> 1, ans;
while(l <= r) {
if(check(mid))
ans = mid, r = mid - 1;
else
l = mid + 1;
}
printf("%d\n", qpow(2, ans));
}
int main() {
File();
Init();
Solve();
return 0;
}