[CF981F] 二分答案 贪心 校内集训 8-2 T2

题目传送门
感谢 xxxhhh x x x h h h 的讲解!!
这是一道很棒的题~~ 模型转化也比较需要思考 
首先这个题可能会无从下手,仔细观察可以发现一个性质,那就是一段新郎一定对应一段连续的新娘,可以用简单证明下,如果存在一个匹配,有一个新郎跨越了另一个新郎的话,那么这肯定不会最优,因为我们可以交换这两个新郎所对应的新娘,使其多出来的一段距离消去,一定会让答案更优。有了这个性质之后我们考虑二分答案,把新娘的序列扩展成三倍,分别代表从左往右跨越起点,从右往左跨越起点和不跨越起点三种情况,把两个序列排序,首先找到第一个新郎能到达的新娘的区间 [l,r] [ l , r ] ,由于新郎必须连续对应一段新娘,那么下一个新郎能到达的新娘的区间就是 [l+1,r+1] [ l + 1 , r + 1 ] 与自己原本能到达区间的交集, 这样如果存在一个新郎没有选择的区间那么当前答案就是不可行的,否则就是可行的,这样就做完了,复杂度 O(nlogL) O ( n l o g L )

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值