1. 程式人生 > >51nod 1672(優先佇列)(樹狀陣列)

51nod 1672(優先佇列)(樹狀陣列)

1672 區間交 

基準時間限制:1 秒 空間限制:131072 KB 分值: 40 難度:4級演算法題

 收藏

 關注

小A有一個含有n個非負整數的數列與m個區間,每個區間可以表示為li,ri。

它想選擇其中k個區間, 使得這些區間的交的那些位置所對應的數的和最大。(是指k個區間共同的交,即每個區間都包含這一段,具體可以參照樣例)

 

在樣例中,5個位置對應的值分別為1,2,3,4,6,那麼選擇[2,5]與[4,5]兩個區間的區間交為[4,5],它的值的和為10。

Input

第一行三個數n,k,m(1<=n<=100000,1<=k<=m<=100000)。
接下來一行n個數ai,表示小A的數列(0<=ai<=10^9)。
接下來m行,每行兩個數li,ri,表示每個區間(1<=li<=ri<=n)。

Output

一行表示答案

Input示例

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

Output示例

10
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<string.h>
#include<vector>
#define maxn 100005
#define ll long long
using namespace std;
struct node
{
    ll st;
    ll la;
    bool operator <(const node &x)
    {
        return st<x.st;
    }
}ac[maxn];
ll a[maxn];
ll sum[maxn];
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    ll n,k,m;
    memset(sum,0,sizeof(sum));
    memset(a,0,sizeof(a));
    scanf("%lld%lld%lld",&n,&k,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=a[i]+sum[i-1];
    }
    for(int i=0;i<m;i++)
    {
        scanf("%lld%lld",&ac[i].st,&ac[i].la);
    }
    sort(ac,ac+m);
    ll ans=0;
    for(ll i=0;i<m;)
    {
        while(q.size()<k)
        {
            q.push(ac[i].la);
            if(q.size()==k)
            ans=max(ans,sum[q.top()]-sum[ac[i].st-1]);
            i++;
        }
        while(q.size()==k)
            q.pop();
    }
    cout<<ans<<endl;
    return 0;
}
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<string.h>
#include<vector>
#define maxn 100005
#define ll long long
using namespace std;
struct node
{
    ll st;
    ll la;
    bool operator <(const node &x)
    {
        return st<x.st;
    }
}ac[maxn];
ll a[maxn];
ll sum[maxn];
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    ll n,k,m;
    memset(sum,0,sizeof(sum));
    memset(a,0,sizeof(a));
    scanf("%lld%lld%lld",&n,&k,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=a[i]+sum[i-1];
    }
    for(int i=0;i<m;i++)
    {
        scanf("%lld%lld",&ac[i].st,&ac[i].la);
    }
    sort(ac,ac+m);
    ll ans=0;
    for(int i=0;i<m;i++)
    {
        q.push(ac[i].la);
        while(q.size()>k) q.pop();
        if(q.size()==k)
        ans=max(ans,sum[q.top()]-sum[ac[i].st-1]);
    }
    cout<<ans<<endl;
    return 0;
}

樹狀陣列調了好久..

#include<iostream>
#include<string.h>
#include<algorithm>
#include<cstdio>
#define maxn 100000
#define ll long long
using namespace std;
struct Tree
{
    int L;
    int R;
    int cover;
}tree[maxn<<2];
struct node
{
    int star;
    int last;
    bool operator <(const node &a)
    {
        return star<a.star;
    }
}ac[maxn];
ll sum[maxn];
void built(int p,int l,int r)
{
    tree[p].L=l;
    tree[p].R=r;
    if(l==r)
    {
        tree[p].cover=0;
        return ;
    }
    int mid=(l+r)>>1;
    built(p<<1,l,mid);
    built(p<<1|1,mid+1,r);
    tree[p].cover=tree[p<<1].cover+tree[p<<1|1].cover;
}
void updata(int p,int x)
{
    if(tree[p].L==tree[p].R)
    {
        tree[p].cover++;
        return ;
    }
    int mid=(tree[p].L+tree[p].R)>>1;
    if(mid>=x)
        updata(p<<1,x);
    else
        updata(p<<1|1,x);
    tree[p].cover=tree[p<<1].cover+tree[p<<1|1].cover;
}
int quety(int p,int x)
{
    if(tree[p].L==tree[p].R)
        return tree[p].L;
    if(tree[p<<1|1].cover>=x)
        return quety(p<<1|1,x);
    else
        return quety(p<<1,x-tree[p<<1|1].cover);
}
int main()
{
    int n,k,m;
    scanf("%d%d%d",&n,&k,&m);
    memset(sum,0,sizeof(sum));
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        sum[i]=sum[i-1]+t;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&ac[i].star,&ac[i].last);
    }
    sort(ac+1,ac+m+1);
    built(1,1,n);
    for(int i=1;i<=k;i++)
    {
        updata(1,ac[i].last);
    }
     ll ans=0;
      ac[m+1].last=0;
     for(int i=k;i<=m;i++)
     {
         int pos=quety(1,k);
         if(pos>=ac[i].star)
            ans=max(ans,sum[pos]-sum[ac[i].star-1]);
         updata(1,ac[i+1].last);
     }
        printf("%lld\n",ans);
    return 0;
}