51 node 区间交 优先队列(min(r),max(l))

/**
链接:http://www.51nod.com/contest/Problem.html#!problemId=1672&contestId=58
题意 : k个区间共同交的最大数对应的和;
分析:窝们需要找到最满足条件的k个区间 进行不断更新取最大值;
首先由于原序列是递增的,因此维护一个优先队列,只需要将r小的放在前面即可;
由于优先队列已经存在了k个 因此窝们每次放进的当前node.l 都是最大的  但是优先队列维护的是最小的右端点;
因此对于这K个区间来说 node.r和a[i].l 就是需要找的最小的右端点和最大的左端点
************************tricsk******************
ll ans = 1e-18 WA    ...... hehe 
*/

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxn=4e5+7;
struct node{
    int l,r;
    friend operator <(node a,node b){
        return a.r>b.r;
    }
}a[maxn];

bool cmp(node a,node b){ return a.l<b.l||(a.l==b.l&&a.r<b.r);}

ll sum[maxn];

priority_queue<node>Q;

int main(){
    int n,k,m,x;scanf("%d %d %d",&n,&k,&m);
    sum[0]=0;
    for(int i=1;i<=n;i++) scanf("%d",&x),sum[i]=sum[i-1]+x;
    for(int i=1;i<=m;i++) scanf("%d %d",&a[i].l,&a[i].r);
    sort(a+1,a+m+1,cmp);
    ll ans=0;
    for(int i=1;i<=m;i++){
        Q.push(a[i]);
        int SZ=Q.size();
        if(Q.size()>k) Q.pop(),SZ--;
        if(Q.size()==k) ans=max(sum[Q.top().r]-sum[a[i].l-1],ans);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hypHuangYanPing/article/details/81808545