题目描述:
Solution
- 对于一个包含的区间,它的左右端点一定是由左端点的最大值以及右端点的最小值构成
- 我们考虑贪心
- 将区间按照左端点从小到大排序,这样就不用考虑左端点的关系了。
- 对于右端点,我们需要维护一个右端点最小值的最大值即可
- 用堆维护,每加进一个区间,就更新堆即可
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,k,m;
struct node{
int l,r;
}a[10100000];
int va[10101000];
int sum[10101000];
priority_queue < int , vector < int > , greater < int > > q;
bool mycmp(node x,node y){
return x.l<y.l;
}
void work(){
int maxx = 0;
while (q.size()) q.pop();
for (int i=1;i<=n;i++) scanf("%lld",&va[i]) , sum[i] = sum[i-1] + va[i];
for (int i=1;i<=m;i++) scanf("%lld %lld",&a[i].l,&a[i].r);
sort(a+1,a+m+1,mycmp);
if (k == 0){
cout<<0<<endl;
return;
}
for (int i=1;i<k;i++) q.push(a[i].r);
for (int i=k;i<=n;i++){
int l = a[i].l , r = min(q.top(),a[i].r);
maxx = max(maxx , sum[r] - sum[l-1]);
if (a[i].r > q.top()) q.pop(),q.push(a[i].r);
}
printf("%lld\n",maxx);
return;
}
signed main(){
while (scanf("%lld %lld %lld",&n,&k,&m)!=EOF) work();
return 0;
}