hdu5700 区间交 思维

来源:互联网 发布:淘宝卡怎么办理 编辑:程序博客网 时间:2024/04/29 03:03

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5700

题目大意:

Problem Description
小A有一个含有n个非负整数的数列与m个区间。每个区间可以表示为li,ri

它想选择其中k个区间, 使得这些区间的交的那些位置所对应的数的和最大。

例如样例中,选择[2,5][4,5]两个区间就可以啦。
 

Input
多组测试数据

第一行三个数n,k,m(1n100000,1km100000)

接下来一行n个数ai,表示lyk的数列(0ai109)

接下来m行,每行两个数li,ri,表示每个区间(1lirin)

 

Output
一行表示答案
 

Sample Input
5 2 31 2 3 4 64 52 51 4
 

Sample Output
10
 


思路:

枚举区间的左端点,找到最小的区间右端点。


#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <fstream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <iomanip>using namespace std;//#pragma comment(linker, "/STACK:102400000,102400000")#define maxn 100005#define MOD 1000000007#define mem(a , b) memset(a , b , sizeof(a))#define LL long long#define ULL unsigned long long#define FOR(i , n) for(int i = 1 ;  i<= n ; i ++)typedef pair<int , int> pii;const long long INF= 0x3fffffff;int n , k , m;LL sum[maxn] ;int  a[maxn];multiset<int>s;vector<int>v[maxn];int main(){    while(scanf("%d %d %d" , &n , &k , &m) != EOF)    {        mem(sum , 0);        s.clear();        int l , r;        FOR(i , n) v[i].clear();        FOR(i , n)        {            scanf("%d" , &a[i]);            sum[i] = sum[i-1] + a[i];        }        FOR(i , m)        {            scanf("%d %d" , &l , &r);            v[l].push_back(r);        }        LL ans = 0;        FOR(i , n)        {            int up = v[i].size();            for(int j = 0 ; j < up ; j ++) s.insert(v[i][j]);            while(s.size() > k) s.erase(s.begin());            if(s.size() == k && *s.begin() >= i)                ans = max(ans , sum[*(s.begin())] - sum[i-1]);        }        printf("%lld\n" , ans);    }    return 0;}


1 0
原创粉丝点击