2016百度之星 hdu 5700 分析+优先队列



链接:戳这里


区间交

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others


Problem Description
小A有一个含有n个非负整数的数列与m个区间。每个区间可以表示为li,ri。

它想选择其中k个区间, 使得这些区间的交的那些位置所对应的数的和最大。

例如样例中,选择[2,5]与[4,5]两个区间就可以啦。
 
Input
多组测试数据

第一行三个数n,k,m(1≤n≤100000,1≤k≤m≤100000)。

接下来一行n个数ai,表示lyk的数列(0≤ai≤109)。

接下来m行,每行两个数li,ri,表示每个区间(1≤li≤ri≤n)。

Output
一行表示答案
 
Sample Input
5 2 3
1 2 3 4 6
4 5
2 5
1 4
 
Sample Output
10


思路:

枚举交的区间的左边界,那么右边界简单分析一下只可能是正好已经覆盖k个区间的最小r

1 4

2 5

4 5

首先区间[1,4]发现只覆盖一个区间  个数<k

接着区间[2,5]存在覆盖区间个数==k,覆盖区间也就是当前的l和最小的r[2,4]  更新答案

然后区间[4,5]存在覆盖区间的个数超过k,那么删掉最小的那个r,因为ai>=0 所以后面的答案显然更优  覆盖区间[4,5]

用优先队列存在每一次插入的r,以当前的l为左边界去更新答案


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int n,k,m;
ll sum[100100];
struct node{
    int l,r;
    bool operator < (const node &a) const{
        if(l==a.l) return r<a.r;
        return l<a.l;
    }
}s[100100];
struct Node{
    int x;
    Node(int x=0):x(x){}
    bool operator < (const Node &a) const{
        return x>a.x;
    }
};
priority_queue<Node> qu;
int main(){
    while(scanf("%d%d%d",&n,&k,&m)!=EOF){
        while(!qu.empty()) qu.pop();
        sum[0]=0;
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            sum[i]=sum[i-1]+x;
        }
        for(int i=1;i<=m;i++) scanf("%d%d",&s[i].l,&s[i].r);
        sort(s+1,s+m+1);
        ll ans=0;
        for(int i=1;i<=m;i++){
            int l=s[i].l,r=s[i].r;
            qu.push(Node(r));
            if(qu.size()<k) continue;
            while(qu.size()>k) qu.pop();
            int x=qu.top().x;
            ans=max(ans,sum[x]-sum[l-1]);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值