zoukankan      html  css  js  c++  java
  • hdu 5700

                      区间交

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


    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
    思路:我们按照右区间从大到小排序,那么我们可以枚举当前K个及以上的区间,从这里面选取K个,这K个里面左端点肯定是越小越好,那么就是当前的第K小了,可用线段树来维护更新
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 
     6 struct node{
     7     int x,y;
     8 }a[N];
     9 ll s[N];
    10 int n,k,m;
    11 bool cmp(node p,node q){
    12     return p.y>q.y;
    13 }
    14 
    15 struct nn{
    16     int l,r;
    17     ll sum;
    18 }e[N*4];
    19 void build(int x,int L,int R){
    20     e[x].l=L;e[x].r=R;
    21     if(L==R){
    22         e[x].sum=0;return ;
    23     }
    24     int mid=(L+R)>>1;
    25     build(2*x,L,mid);
    26     build(2*x+1,mid+1,R);
    27     e[x].sum=e[x*2].sum+e[2*x+1].sum;
    28 }
    29 void update(int v,int x){
    30     if(e[x].l==e[x].r){
    31         e[x].sum++;return ;
    32     }
    33     int mid=(e[x].l+e[x].r)>>1;
    34     if(v<=mid)  update(v,2*x);
    35     else update(v,2*x+1);
    36     e[x].sum=e[x*2].sum+e[2*x+1].sum;
    37 }
    38 
    39 int query(int v,int x){
    40     if(e[x].l==e[x].r){
    41         return e[x].l;
    42     }
    43     if(e[2*x].sum>=v) query(v,2*x);
    44     else query(v-e[x*2].sum,2*x+1);
    45 }
    46 int main(){
    47     while(scanf("%d%d%d",&n,&k,&m)!=EOF){
    48     ll x;
    49     build(1,1,n);
    50     for(int i=1;i<=n;i++){
    51         scanf("%lld",&x);s[i]=s[i-1]+x;
    52     }
    53     for(int i=1;i<=m;i++){
    54         scanf("%d%d",&a[i].x,&a[i].y);
    55     }
    56     sort(a+1,a+1+m,cmp);
    57     for(int i=1;i<=k-1;i++){
    58         update(a[i].x,1);
    59     }
    60     ll Max=0;
    61     for(int i=k;i<=m;i++){
    62         update(a[i].x,1);
    63        // cout<<e[1].sum<<endl;
    64         int xx=query(k,1);
    65         //cout<<xx<<" "<<a[i].y<<endl;
    66         if(xx<=a[i].y){
    67             Max=max(Max,s[a[i].y]-s[xx-1]);
    68         }
    69     }
    70     cout<<Max<<endl;
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    MongoDB数据查询详解
    MongoDB增加数据
    laravel安装初体验
    操作MongoDB
    MongoDB基本概念和安装配置
    tp5操作mongo
    c语言运算符优先级与while循环案例
    tp5下通过composer实现日志记录功能
    c语言中类型转换与赋值运算符、算术运算符、关系运算符、逻辑运算符。原码、反码、补码。小解。
    scanf使用与运算符
  • 原文地址:https://www.cnblogs.com/hhxj/p/7103719.html
Copyright © 2011-2022 走看看