zoukankan      html  css  js  c++  java
  • D. Fedor and coupons 二分暴力

    http://codeforces.com/contest/754/problem/D

    给出n条线段,选出k条,使得他们的公共部分长度最大。

    公共部分的长度,可以二分出来,为val。那么怎么判断有k条线段有共同的这个长度,而且选他们出来呢?

    可以把右端点减去val - 1,那么以后就只需要k条线段至少有一个交点就可以了。

    那么怎么确定这个交点呢?

    我的做法是直接离散,然后暴力找出覆盖次数>=k的那个点。

    复杂度好像有点高,

    log2e10 * nlogn

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 6e5 + 20;
    int L[maxn], R[maxn];
    int pos[maxn];
    int book[maxn];
    int n, k;
    map<LL, int>save;
    bool check(LL val) {
        if (val == 0) return true;
        int lenpos = 0;
        for (int i = 1; i <= n; ++i) {
            if (R[i] - L[i] + 1 < val) continue;
            pos[++lenpos] = L[i];
            pos[++lenpos] = R[i] - val + 1;
        }
        int mx = -inf;
        if (lenpos == 0) return false;
        sort(pos + 1, pos + 1 + lenpos);
        for (int i = 1; i <= n; ++i) {
            if (R[i] - L[i] + 1 < val) continue;
            int t1 = lower_bound(pos + 1, pos + 1 + lenpos, L[i]) - pos;
            int t2 = lower_bound(pos + 1, pos + 1 + lenpos, R[i] - val + 1) - pos;
            book[t1]++;
            book[t2 + 1]--;
            mx = max(mx, t2 + 1);
        }
        bool flag = false;
        for (int i = 1; i <= mx; ++i) {
            book[i] += book[i - 1];
            if (book[i] >= k) {
    //            assert(save[val] == 0);
                save[val] = pos[i];
                flag = true;
                break;
            }
        }
        for (int i = 1; i <= mx; ++i) book[i] = 0;
        return flag;
    }
    void work() {
        cin >> n >> k;
        for (int i = 1; i <= n; ++i) {
            cin >> L[i] >> R[i];
        }
        LL be = 0, en = 2e10;
        while (be <= en) {
            LL mid = (be + en) >> 1;
            if (check(mid)) {
                be = mid + 1;
            } else en = mid - 1;
        }
        cout << en << endl;
        if (en == 0) {
            for (int i = 1; i <= k; ++i) {
                cout << i << " ";
            }
        } else {
            int use = 0;
            int tpoint = save[en];
    //        cout << tpoint << endl;
            for (int i = 1; i <= n && use < k; ++i) {
                if (R[i] - tpoint + 1 < en) continue;
                if (tpoint >= L[i] && tpoint <= R[i]) {
                    use++;
                    cout << i << " ";
                }
            }
    //        assert(use == k);
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        IOS;
        work();
        return 0;
    }
    View Code

    其实这题关键要把判断k条线段相交于同一个区间,化简为相交于同一个点

  • 相关阅读:
    ThreadLocal
    layer.open()中属性content在IE 8中提示“网页无法显示”
    前端String类型转JSON类型
    表单异常自动提交
    div中图片居中
    使用struts2的内置标签,采用submit()提交表单时,浏览器报404
    使用@Test报java.lang.NullPointerException at org.eclipse.jdt.internal.junit4.runner.SubForestFilter.shouldRun(SubForestFilter.java:81)异常
    java web程序上传文件,浏览器显示连接被重置
    java导入ldif文件
    LDAP常见错误码
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6271134.html
Copyright © 2011-2022 走看看