题意:中文
思路:本弱并不会,看了看出题人的题解,总是感觉被智商压制了,首先要按左端点排序,然后右端点的位置在线段树中更新+1,然后对于每一个区间来说,以这个区间的左端点为开始,那么我们就要找一个最远的右端点且被覆盖过K次的那个点,这就要在查询时来完成这个要求了,与其说是算法还不如说是想法题
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
int num[maxn<<2];
ll sum[maxn];
void update(int pos,int le,int ri,int node){
if(le==ri){
num[node]++;
return ;
}
int t=(le+ri)>>1;
if(pos<=t) update(pos,le,t,node<<1);
else update(pos,t+1,ri,node<<1|1);
num[node]=num[node<<1]+num[node<<1|1];
}
int query(int k,int le,int ri,int node){
if(le==ri) return le;
int t=(le+ri)>>1;
if(num[node<<1|1]>=k) return query(k,t+1,ri,node<<1|1);
else return query(k-num[node<<1|1],le,t,node<<1);
}
struct node{
ll x,y;
}A[maxn];
bool cmp(const node &a,const node &b){
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
int main(){
int n,m,k;
ll a;
while(scanf("%d%d%d",&n,&k,&m)!=-1){
for(int i=1;i<=n;i++) scanf("%I64d",&a),sum[i]=sum[i-1]+a;
for(int i=0;i<m;i++) scanf("%I64d%I64d",&A[i].x,&A[i].y);
sort(A,A+m,cmp);
memset(num,0,sizeof(num));
for(int i=0;i<k;i++) update(A[i].y,1,n,1);
ll ans=0;
for(int i=k-1;i<m;i++){
int pos=query(k,1,n,1);
if(pos>=A[i].x&&pos<=A[i].y) ans=max(ans,sum[pos]-sum[A[i].x-1]);
update(A[i+1].y,1,n,1);
}
printf("%I64d\n",ans);
}
return 0;
}