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

    区间交

    题目连接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5700

    Description

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

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

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

    Input

    多组测试数据

    第一行三个数n,k,m(1≤n≤100000,1≤k≤m≤100000)。

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

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

    Output

    一行表示答案

    Sample Input

    5 2 3
    1 2 3 4 6
    4 5
    2 5
    1 4

    Sample Output

    10

    Hint

    题意

    题解:

    离线线段树,线段树维护区间和就好了

    我暴力枚举左端点,然后每次使得在这个左端点上的区间的右端点++就好了

    那么显然从i开始到这个位置的前缀和,就是这个点覆盖了多少次

    那么我们通过在线段树上二分去找这个点就好了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+7;
    int n,k,m;
    long long t[maxn*4],sum[maxn],a[maxn],l,r;
    vector<int> E[maxn];
    void build(int x,int l,int r)
    {
        t[x]=0;
        if(l==r)return;
        int mid=(l+r)/2;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
    }
    void update(int x,int l,int r,int pos)
    {
        if(l==r)
        {
            t[x]++;
            return;
        }
        int mid=(l+r)/2;
        if(pos<=mid)update(x<<1,l,mid,pos);
        else update(x<<1|1,mid+1,r,pos);
        t[x]=t[x<<1]+t[x<<1|1];
    }
    int query(int x,int l,int r,int p)
    {
        if(t[x]<p)return -1;
        if(l==r)return l;
        int mid=(l+r)/2;
        if(p<=t[x<<1|1])return query(x<<1|1,mid+1,r,p);
        else return query(x<<1,l,mid,p-t[x<<1|1]);
    }
    void solve()
    {
        build(1,1,n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            sum[i]=sum[i-1]+a[i];
            E[i].clear();
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            E[l].push_back(r);
        }
        long long ans = 0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<E[i].size();j++)update(1,1,n,E[i][j]);
            int p=query(1,1,n,k);
            if(p>=i)ans=max(ans,sum[p]-sum[i-1]);
        }
        printf("%lld
    ",ans);
    }
    int main()
    {
        while(cin>>n>>k>>m)
            solve();
    }
  • 相关阅读:
    P4720 【模板】扩展卢卡斯
    P3211 [HNOI2011]XOR和路径
    ZOJ 3329 One Person Game
    CF817F MEX Queries
    P3239 [HNOI2015]亚瑟王
    P3412 仓鼠找sugar II
    P4111 [HEOI2015]小Z的房间
    P4008 [NOI2003]文本编辑器
    CF451E Devu and Flowers
    P3975 [TJOI2015]弦论
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5522550.html
Copyright © 2011-2022 走看看