2275: 跳跳的区间游戏
时间限制: 2 Sec 内存限制: 128 MB提交: 50 解决: 12
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
跳跳来到了第二个游戏,游戏规则为,跳跳有一个含有n个非负整数的数列与m个区间,每个区间可以表示为li,ri。
他要选择其中k个区间, 并使得这些区间的交的那些位置所对应的数的和最大。(是指k个区间共同的交,即每个区间都包含这一段,具体可以参照样例)
在样例中,5个位置对应的值分别为1,2,3,4,6,那么选择2,5与4,5两个区间的区间交为4,5,它的值的和为10。
输入
第一行输入三个整数n,k,m(1<=n<=100000,1<=k<=m<=100000)。
接下来一行n个整数ai,表示小A的数列(0<=ai<=10^9)。
接下来m行,每行两个整数li,ri,表示每个区间(1<=li<=ri<=n)。
输出
一行表示答案
样例输入
5 2 3
1 2 3 4 6
4 5
2 5
1 4
样例输出
10
按照左端点排序,枚举区间,先把右端点放入队列里,首先把队列里小于当前枚举区间l的全都pop掉,因为肯定不相交;然后如果队列里的数量大于等于k把前面的扔掉,因为后面的右端点一定比前面最优,这样,这个区间就是 (l ,q.top()),这一块被覆盖了k次,前缀和可以直接求出它的值,然后更新ans就好了
#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
struct node{
int x,y;
}mat[100005];
ll sum[100005];
int cmp(node a,node b)
{
return a.x <b.x ;
}
int main()
{
int n,m,k;
long long a;
sum[0]=0;
while(~scanf("%d%d%d",&n,&k,&m))
{
priority_queue<int,vector<int>,greater<int> >q;
for(int i=1;i<=n;i++)
{//预处理,计算前缀和
scanf("%lld",&a);
sum[i]=sum[i-1]+a;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&mat[i].x ,&mat[i].y);
}
ll ans=0;
sort(mat,mat+m,cmp);
for(int i=0;i<m;i++)
{//开始枚举
q.push(mat[i].y);
while(q.size()>k||q.top()<mat[i].x)
{//如果>k,删除右端点小的,右端点大的更优||队列中的与当前i不不相交
q.pop();
}
if(q.size()==k&&q.top()>=mat[i].x)//更新ans值
ans=max(ans,sum[q.top()]-sum[mat[i].x-1]);
}
printf("%lld\n",ans);
}
return 0;
}