区间交

区间交

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 3 1 2 3 4 6 4 5 2 5 1 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;
}
点赞