HDU 5700 区间交(线段树)

题目链接 区间交

给定n和k,求k个区间,使得这K个区间的交集的数的和最大。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)    for (int i(a); i <= (b); ++i)
#define dec(i, a, b)    for (int i(a); i >= (b); --i)

#define lson i << 1, L, mid
#define rson i << 1 | 1, mid + 1, R

typedef long long LL;

const int N = 200010;

struct node{
        int l, r;
        friend bool operator < (const node &a, const node &b){
            return a.l < b.l;
        }
} a[N];

int tree[N << 2];
int n, k, m;
LL sum[N], ans, x;

void pushup(int i){ tree[i] = tree[i << 1] + tree[i << 1 | 1];  }


void update(int i, int L, int R, int x){
        if (L == R){ ++tree[i]; return;}
        int mid = (L + R) >> 1;
        if (x <= mid) update(lson, x); else update(rson, x);
        pushup(i);
}

int query(int i, int L, int R, int x){
        if (L == R) return L;
        int mid = (L + R) >> 1;
        if (tree[i << 1 | 1] >= x) return query(rson, x);
        else return query(lson, x - tree[i << 1 | 1]);
}

int main(){

        while (~scanf("%d%d%d", &n, &k, &m)){
            sum[0] = 0; ans = 0;
            memset(tree, 0, sizeof tree);
            rep(i, 1, n){
                    scanf("%lld", &x);
                    sum[i] = sum[i - 1] + x;
            }

            rep(i, 1, m) scanf("%d%d", &a[i].l, &a[i].r);
            sort(a + 1, a + m + 1);
            dec(i, k, 1) update(1, 1, n, a[i].r);
            a[m + 1].r = 1;
            rep(i, k, m){
                    int pos = query(1, 1, n, k);
                    if (pos >= a[i].l) ans = max(ans, sum[pos] - sum[a[i].l - 1]);
                    update(1, 1, n, a[i + 1].r);
            }    

            printf("%lld\n", ans);
        }
        return 0;
}

 

posted @ 2017-04-08 20:12  cxhscst2  阅读(158)  评论(0编辑  收藏  举报