Problem Description
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
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<bitset>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 10;
int n, m, k,x,l,r;
LL sum[maxn],ans;
int ft[maxn],nt[maxn],u[maxn],sz;
int f[maxn<<3];
void insert(int x,int l,int r,int v)
{
++f[x];
if (l==r) return;
int mid=l+r>>1;
if (v<=mid) insert(x<<1,l,mid,v);
else insert(x<<1|1,mid+1,r,v);
}
int get(int x,int l,int r,int v)
{
if (l==r) return l;
int mid=l+r>>1;
if (f[x<<1|1]>=v) return get(x<<1|1,mid+1,r,v);
else return get(x<<1,l,mid,v-f[x<<1|1]);
}
int main()
{
while (~scanf("%d%d%d",&n,&k,&m))
{
memset(f,0,sizeof(f));
ans=sum[0]=sz=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
sum[i]=sum[i-1]+x;
ft[i]=-1;
}
for (int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
u[sz]=r;
nt[sz]=ft[l];
ft[l]=sz++;
}
int tot=0;
for (int i=1;i<=n;i++)
{
for (int j=ft[i];j!=-1;j=nt[j])
{
tot++;
insert(1,1,n,u[j]);
}
if (tot<k) continue;
ans=max(ans,sum[get(1,1,n,k)]-sum[i-1]);
}
cout<<ans<<endl;
}
return 0;
}