思路:
很经典的区间贪心问题,按照区间左端点排序,用优先队列维护一下区间右端点。
- 首先求一下前缀和,之后将区间按照起始时间从小到大排序,对于每个区间,首先将右端点放入优先队列,之后删除堆顶比当前的左端点小的值,若队列里的值多于k个,那么删除到只剩k个,当前的最优区间就是[node[i].s,top()],根据这个值更新Max即可。
代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int Max_n=1e6+10;
int n,m,k;
struct Node{
int s,t;
bool operator<(const Node& n)const{
return s<n.s;
}
}node[Max_n];
int a[Max_n];
ll sum[Max_n];
priority_queue<int,vector<int>,greater<int> >que;
int main()
{
scanf("%d%d%d",&n,&k,&m);
sum[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
for(int i=0;i<m;i++)
scanf("%d%d",&node[i].s,&node[i].t);
sort(node,node+m);
ll Max=0;
for(int i=0;i<m;i++){
que.push(node[i].t);
while(que.top()<node[i].s||que.size()>k)que.pop();
if(que.size()==k)
Max=max(Ma,sum[que.top()]-sum[node[i].s-1]);
}
printf("%lld\n",Max);
return 0;
}