zoukankan      html  css  js  c++  java
  • HDU 5700 区间交(线段树)

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

    【题目大意】

      给出一个长度为n的数列和m个区间,现在求k个区间,使得他们的区间交内的数列项和最大。

    【题解】

      将区间按照右端点为第一关键字排序,
      那么在从后往前扫描的过程中,已经扫过的部分右端点一定大于当前
      所以我们可以枚举区间交的右端点,找出第k小的左端点,来更新答案
      因为右端点固定,因此左端点越小,答案一定越大,
      所以枚举右端点不会遗漏答案。

    【代码】

    #include <cstdio> 
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=200000,M=200000;
    typedef long long LL;
    int k,q,x,y,T[M<<2],n,m;
    void up(int x){T[x]=T[x<<1]+T[x<<1|1];}
    void update(int t,int num,int l,int r,int x){
        if(l==r){T[x]+=num;return;}
        int mid=(l+r)>>1;
        if(t<=mid)update(t,num,l,mid,x<<1);
        else update(t,num,mid+1,r,x<<1|1);
        up(x);
    } 
    int find(int k,int l,int r,int x){
        int mid=(l+r)>>1,tmp=T[x<<1];
        if(l==r)return l;
        if (k<=tmp)return find(k,l,mid,x<<1);
        else return find(k-tmp,mid+1,r,x<<1|1);
    }
    LL s[N];
    struct data{int l,r;}p[N];
    bool cmp(data a,data b){return a.r<b.r||a.r==b.r&&a.l<b.l;}
    int main(){
        while(~scanf("%d%d%d",&n,&k,&m)){
            memset(T,0,sizeof(T));
            for(int i=1;i<=n;i++){
                scanf("%d",&x);
                s[i]=s[i-1]+x;
            }for(int i=1;i<=m;i++)scanf("%d%d",&p[i].l,&p[i].r);
            sort(p+1,p+m+1,cmp);
            for(int i=m;i>m-k+1;i--)update(p[i].l,1,1,n,1);
            LL ans=0;
            for(int i=m-k+1;i;i--){
                update(p[i].l,1,1,n,1);
                int t=find(k,1,n,1);
                if(t<=p[i].r)ans=max(ans,s[p[i].r]-s[t-1]);
            }printf("%lld
    ",ans);
        }return 0;
    }
    

      

  • 相关阅读:
    javascript获取xml节点的最大值
    iis 不能浏览aspx页面
    批量替换文件夹里面的文本文件的指定字符
    select update delete
    SQL IAM的理解
    数据库的页构成
    sqltype IsDBNull
    MSSQL优化教程之1.4 其他几种类型的页面
    SqlDataAdapter
    行状态,行版本
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu5700.html
Copyright © 2011-2022 走看看