hdu 5700区间交(线段树)

区间交

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


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
/*
hdu 5700区间交(线段树)

problem:
给你一串数字以及m个区间,然后选择其中的k个区间使区间相交区域的和最大

solve:
最开始想的是二分答案然后判断能否找出k个区间使其的和达到,但是推着推着发现和以前的做过的线段树处理区间问题很像
枚举区间的右端点,然后找出左边哪个端点使其刚好覆盖的k个区间,然后求值取最大值
所以需要维护左端的个数,以及查找出第k小的左端点,用线段树解决.
因为枚举的是以当前点为最终区间的右端点,所以出现过的区间要除去(即删除它的左端点).

hhh-2016-08-13 15:15:56
*/
#include <iostream>
#include <vector>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
using namespace std;
#define lson  (i<<1)
#define rson  ((i<<1)|1)
typedef long long ll;
typedef unsigned int ul;
const int INF = 0x3f3f3f3f;
const int  maxn = 100000+10;
const int mod = 1e9+7;

struct Tree
{
    int l,r;
    int lval,mid;
} tree[maxn<<2];

void push_up(int i)
{
    tree[i].lval = tree[lson].lval+tree[rson].lval;
}

void build(int i,int l,int r)
{
    tree[i].l = l,tree[i].r = r,tree[i].lval = 0;
    if(l == r)
        return;
    tree[i].mid= (l+r) >>1;
    int mid = tree[i].mid;
    build(lson,l,mid);
    build(rson,mid+1,r);
    push_up(i);
}

void Insert(int i,int k,int val)
{
    if(tree[i].l == tree[i].r && tree[i].l == k)
    {
        tree[i].lval += val;
//        cout <<"pos: " << tree[i].l <<" val: "<<tree[i].lval<< endl;
        return ;
    }
//    cout <<tree[i].l << " "<< tree[i].r << "k "<<k <<" val: "<<val<< endl;
    int mid = tree[i].mid;

    if(k <= mid)
        Insert(lson,k,val);
    else
        Insert(rson,k,val);
    push_up(i);
//    cout <<tree[i].l << " "<< tree[i].r <<" val: "<<tree[i].lval<< endl;
}

int query(int i ,int k)
{
//    cout << tree[i].lval << " " <<tree[i].l << " "<< tree[i].r <<endl;
    if(tree[i].l == tree[i].r)
        return tree[i].l;
    if(k <= tree[lson].lval)
        return query(lson,k);
    else
       return  query(rson,k-tree[lson].lval);
    push_up(i);
}

int query_num(int i,int l,int r)
{
    if(tree[i].l >= l && tree[i].r <= r)
    {
        return tree[i].lval;
    }
    int num = 0;
    if(l <= tree[i].mid)
        num += query_num(lson,l,r);
    if(r > tree[i].mid)
        num += query_num(rson,l,r);
    return num;
}

struct node
{
    int l,r;
} pnode[maxn];

ll Max(ll a,ll b)
{
    if(a < b)
        return b;
    return a;
}

bool cmp(node a,node b)
{
    if(a.r != b.r)
        return a.r < b.r;
    else
        return a.l < b.l;
}
ll num[maxn];
int main()
{
    int n,k,m;
    while(scanf("%d%d%d",&n,&k,&m) != EOF)
    {
        num[0] = 0;
        build(1,1,n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d",&num[i]);
            num[i] += num[i-1];
        }
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d",&pnode[i].l,&pnode[i].r);
            Insert(1,pnode[i].l,1);
        }
        sort(pnode+1,pnode+m+1,cmp);

        int now = 1;
        ll ans = 0;
        for(int i = 1; i <= n && now <= m; i++)
        {
            if(i == pnode[now].r)
            {
//                cout << "r:"<<pnode[now].r << endl;
                int t = query_num(1,1,i);
                if(t >= k)
                {
                    int l = query(1,k);
//                     cout<<"l:" << l << endl;
                    ans = Max(ans,num[i]-num[l-1]);
                }
//                cout<<"ans:"<<ans <<"  t:" << t << endl;
            }
            while(now <= m && pnode[now].r == i)
            {
                Insert(1,pnode[now].l,-1);
                now ++;
            }
        }
        cout << ans <<endl;
    }
    return 0;
}

/*
5 2 3
1 2 3 4 5
1 2
3 4
5 5
*/

  

原文地址:https://www.cnblogs.com/Przz/p/5792145.html