hdu-5700 区间交(二分+树状数组)

时间:2023-12-01 14:55:44

题目链接:

区间交

Problem Description

小A有一个含有n个非负整数的数列与mm个区间。每个区间可以表示为l​i​​,r​i​​。

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

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

Input

多组测试数据

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

接下来一行n个数a​i​​,表示lyk的数列(0≤a​i​​≤10​9​​)。

接下来m行,每行两个数l​i​​,r​i​​,表示每个区间(1≤l​i​​≤r​i​​≤n)。

Output

一行表示答案

Sample Input
5 2 3
1 2 3 4 6
4 5
2 5
1 4
Sample Output
10

题意:

思路:

求相交区间和的最大值,首先是树状数组sum可以求log(n)求区间和,在找区间的时候枚举左端点,二分右端点,先把区间按左端点排序,然后一边更新一边询问,由于按左端点排序,所以左端点可以作为相交区间的左端点,二分右端点时询问这个点是否被大于等于k次覆盖,找到右端点最大的那个点,此时对应的区间就是这个左端点能得到的最大的区间,枚举完左端点就可以找到最大值了;
复杂度好像是mlog(n)log(n); AC代码:
#include <bits/stdc++.h>
/*
#include <iostream>
#include <queue>
#include <cmath>
#include <map>
#include <cstring>
#include <algorithm>
#include <cstdio>
*/
using namespace std;
#define Riep(n) for(int i=1;i<=n;i++)
#define Riop(n) for(int i=0;i<n;i++)
#define Rjep(n) for(int j=1;j<=n;j++)
#define Rjop(n) for(int j=0;j<n;j++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef long long LL;
const LL mod=1e9+;
const double PI=acos(-1.0);
const int inf=0x3f3f3f3f;
const int N=1e5+;
int n,k,m;
LL a[N];
LL sum[N];
int num[N];
struct node
{
int l,r;
}po[N];
int cmp(node x,node y)
{
if(x.l==y.l)x.r>y.r;
return x.l<y.l;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x,LL y)
{
while(x<=n)
{
sum[x]+=y;
x+=lowbit(x);
}
}
LL query(int pos)
{
LL ans=;
while(pos>)
{
ans+=sum[pos];
pos-=lowbit(pos);
}
return ans;
}
void update1(int x,int flag)
{
while(x<=n)
{
num[x]+=flag;
x+=lowbit(x);
}
}
int query1(int x)
{
int ans=;
while(x>)
{
ans+=num[x];
x-=lowbit(x);
}
return ans;
}
int check(int x)
{
if(query1(x)>=k)return ;
return ;
}
int main()
{
while(scanf("%d%d%d",&n,&k,&m)!=EOF)
{
LL ans=;
mst(num,);
mst(sum,);
Riep(n)scanf("%lld",&a[i]),update(i,a[i]);
Riep(m)scanf("%d%d",&po[i].l,&po[i].r);
sort(po+,po+m+,cmp);
for(int i=;i<=m;i++)
{
update1(po[i].l,);
update1(po[i].r+,-);
int L=po[i].l,R=po[i].r;
while(L<=R)
{
int mid=(L+R)>>;
if(check(mid))L=mid+;
else R=mid-;
}
LL fx=query(L-),fy;
if(po[i].l>)fy=query(po[i].l-);
else fy=;
ans=max(ans,fx-fy);
}
printf("%lld\n",ans);
}
return ;
}