zoukankan      html  css  js  c++  java
  • hdu-5700 区间交(二分+树状数组)

    题目链接:

    区间交

    Problem Description
     

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

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

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

    Input
     

    多组测试数据

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

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

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

    Output
     

    一行表示答案

    Sample Input
     
    5 2 3
    1 2 3 4 6
    4 5
    2 5
    1 4
    Sample Output
     
    10

    题意:


    思路:

    求相交区间和的最大值,首先是树状数组sum可以求log(n)求区间和,在找区间的时候枚举左端点,二分右端点,先把区间按左端点排序,然后一边更新一边询问,由于按左端点排序,所以左端点可以作为相交区间的左端点,二分右端点时询问这个点是否被大于等于k次覆盖,找到右端点最大的那个点,此时对应的区间就是这个左端点能得到的最大的区间,枚举完左端点就可以找到最大值了;
    复杂度好像是mlog(n)log(n);


    AC代码:

    #include <bits/stdc++.h>
    /*
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    */
    using namespace std;
    #define Riep(n) for(int i=1;i<=n;i++)
    #define Riop(n) for(int i=0;i<n;i++)
    #define Rjep(n) for(int j=1;j<=n;j++)
    #define Rjop(n) for(int j=0;j<n;j++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
    typedef long long LL;
    const LL mod=1e9+7;
    const double PI=acos(-1.0);
    const int inf=0x3f3f3f3f;
    const int N=1e5+4;
    int n,k,m;
    LL a[N];
    LL sum[N];
    int num[N];
    struct node
    {
        int l,r;
    }po[N];
    int cmp(node x,node y)
    {
        if(x.l==y.l)x.r>y.r;
        return x.l<y.l;
    }
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int x,LL y)
    {
        while(x<=n)
        {
            sum[x]+=y;
            x+=lowbit(x);
        }
    }
    LL query(int pos)
    {
        LL ans=0;
        while(pos>0)
        {
            ans+=sum[pos];
            pos-=lowbit(pos);
        }
        return ans;
    }
    void update1(int x,int flag)
    {
        while(x<=n)
        {
            num[x]+=flag;
            x+=lowbit(x);
        }
    }
    int query1(int x)
    {
        int ans=0;
        while(x>0)
        {
                ans+=num[x];
                x-=lowbit(x);
        }
        return ans;
    }
    int check(int x)
    {
        if(query1(x)>=k)return 1;
        return 0;
    }
    int main()
    {
            while(scanf("%d%d%d",&n,&k,&m)!=EOF)
            {
                LL ans=0;
                mst(num,0);
                mst(sum,0);
                Riep(n)scanf("%lld",&a[i]),update(i,a[i]);
                Riep(m)scanf("%d%d",&po[i].l,&po[i].r);
                sort(po+1,po+m+1,cmp);
                for(int i=1;i<=m;i++)
                {
                    update1(po[i].l,1);
                    update1(po[i].r+1,-1);
                    int L=po[i].l,R=po[i].r;
                    while(L<=R)
                    {
                        int mid=(L+R)>>1;
                        if(check(mid))L=mid+1;
                        else R=mid-1;
                    }
                    LL fx=query(L-1),fy;
                    if(po[i].l>1)fy=query(po[i].l-1);
                    else fy=0;
                    ans=max(ans,fx-fy);
                }
                printf("%lld
    ",ans);
            }
        return 0;
    }
  • 相关阅读:
    狐狸和兔子
    Arguments to main
    strncpy
    atoi
    sscanf
    集体的智慧:为什么SaaS打败企业软件?
    终于来热风了,又一次感觉到什么叫温暖!
    博士生的毕设
    淡淡的
    endnote如何修改输出格式?
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5526640.html
Copyright © 2011-2022 走看看