链接:戳这里
区间交
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;
}