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; }