区间交

来源:互联网 发布:thinkphp外卖系统源码 编辑:程序博客网 时间:2024/04/24 21:07

区间交

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 652    Accepted Submission(s): 308



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
 

题解:

         题目要求从m个区间中找出k个区间的交区间,且交区间的sum(a[l],a[r])的和最大. 我们可以考虑转换这个问题.变为求原序列的一段区间被多少个区间覆盖.

         假设当前找的是区间[L,R],那么很显然某个区间要包含这个[L,R],它的左右端点必须要L,R的两边. 知道这个,我们只需要处理那些左端点<=L的.然后再通过树状

         数组求出有多少个右端点>=R.然后对于原序列的区间,只需要尺取一下就行了.


AC代码:

#include <iostream>#include <string.h>#include <map>#include <set>#include <stack>#include <vector>#include <stdio.h>#include <algorithm>using namespace std;typedef long long ll;const int N = 1e5 + 10;int a[N],c[N];struct Interval{    int l,r;    void read()    {        scanf("%d %d",&l,&r);    }    bool operator < (const Interval &a) const    {        return l < a.l;    }} interval[N];void add(int x,int n){    while(x <= n)    {        c[x]++;        x += x & -x;    }}int get(int x){    int s = 0;    x--;    while(x > 0)    {        s += c[x];        x -= x & -x;    }    return s;}void solve(){    int n,k,m;    while(~scanf("%d %d %d",&n,&k,&m))    {        memset(c,0,sizeof c);        for(int i = 1; i <= n; ++i) scanf("%d",&a[i]);        for(int i = 1; i <= m; ++i) interval[i].read();        sort(interval + 1,interval + m + 1);        ll ans = 0,sum = 0;        int l,pos;        pos = l = 1;        for(int r = 1; r <= n; ++r)        {            sum += a[r];            while(l <= r)            {                while(pos <= m && interval[pos].l <= l)                    add(interval[pos++].r,n);                int num = pos - 1 - get(r);                if(num >= k)                {                    ans = max(ans,sum);                    break;                }                else                {                    sum -= a[l];                    l++;                }            }        }        cout << ans << endl;    }}int main(){    solve();    return 0;}


0 0