Codeforces Round #422 C. Hacker, pack your bags! (二分)

题意

有 n 个旅行行程,每个指定 l r cost ,表示该行程的出发时间,结束时间,费用,旅行的持续时间记为 r-l+1

要求找到两个旅行行程,使得两者的持续时间和恰好为 x 。同时保证两个行程不会冲突,即需保证 ri<lj rj<li 。在能够找到的情况下,要求找到总费用最少的方案。

解题思路

将旅行行程按持续时间为第一关键字从小到大,结束时间为第二关键字从小到大排序。

统计前缀和为 同持续时间下,在结束时间 ri 前的行程的最小费用。

枚举每个行程 i 作为两个行程的后出发行程,每个 i 通过二分查找先出发行程 j 。在满足 v[i].duration + v[j].duration == xv[i].l > v[j].j 的情况下,记录最小的费用 minCost 。详细操作见函数 findMinTwins()

总体复杂度为 O(NlogN)

代码

import java.io.*;
import java.util.*;

/**
 * Created by Utop on 2017/7/3.
 */
public class C {

    static long INF = 1l<<60;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int x = Integer.parseInt(st.nextToken());

        Voucher[] v = new Voucher[n];

        for (int i=0;inew StringTokenizer(br.readLine());
            int l = Integer.parseInt(st.nextToken());
            int r = Integer.parseInt(st.nextToken());
            int cost = Integer.parseInt(st.nextToken());
            v[i] = new Voucher(l, r, cost, r-l+1, cost);
        }

        Arrays.sort(v, new CMP());

        for (int i=0;iif (i>0 && v[i].duration == v[i-1].duration) {
                v[i].minCost = Math.min(v[i].minCost, v[i-1].minCost);
            }
        }

        long ansCost = INF;
        for (int i=0;i0, n-1, x), ansCost);
        }
        if (ansCost == INF) {
            bw.write("-1");
        } else {
            bw.write(String.valueOf(ansCost));
        }
        bw.flush();
        bw.close();

    }

    private static long findMinTwins(Voucher[] v, int rightPart, int l, int r, int x) {

        int mid;
        long ans = INF;
        while (l <= r) {
            mid = (l+r) >> 1;
            if (v[rightPart].duration + v[mid].duration < x) {
                l = mid + 1;
            } else if (v[rightPart].duration + v[mid].duration == x) {
                if (v[rightPart].l <= v[mid].r) {
                    r = mid - 1;
                } else {
                    l = mid + 1;
                    ans = Math.min(ans, v[rightPart].cost + v[mid].minCost);
                }
            } else {
                r = mid - 1;
            }
        }
        return ans;
    }

    static class Voucher extends ArrayList{
        int l, r, cost, duration, minCost;
        Voucher(int _l, int _r, int _cost, int _duration, int _minCost) {
            this.l = _l;
            this.r = _r;
            this.cost = _cost;
            this.duration = _duration;
            this.minCost = _minCost;
        }
    }

    static class CMP implements Comparator {

        @Override
        public int compare(Object o1, Object o2) {
            Voucher v1 = (Voucher)o1;
            Voucher v2 = (Voucher)o2;
            if (v1.duration == v2.duration) {
                if (v1.r == v2.r)   return 0;
                return v1.r < v2.r ? -1 : 1;
            }
            return v1.duration < v2.duration ? -1 : 1;
        }
    }
}

你可能感兴趣的:(Codeforces)