有N个人要去膜拜JZ,他们不知道JZ会出现在哪里,因此每个人有一个活动范围,只要JZ出现在这个范围内就能被膜拜,
伟大的JZ当然希望膜拜他的人越多越好,但是JZ不能分身,因此只能选择一个位置出现,他最多可以被多少人膜拜呢,
这个简单的问题JZ当然交给你了
A_i..B_i (1 <=A_i <= B_i <= 1,000,000,000)
N (1 <= N <= 50,000)
4
4 8
1 2
5 10
3 5
输出
3
思路:考虑到a,b的范围很大,N范围小,果断离散化一下,
离散化以后,如果直接 add[] 暴力统计区间,会超时,考虑线段树,使用懒惰标记 500ms
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
struct data
{
int c;
int temp;
int no;
}s[100009];
int cmp(data a,data b)
{
return a.c<b.c;
}
int cmp1(data a,data b)
{
return a.no<b.no;
}
int count1[100009];
struct abc
{
int l,r;
int all;
int hou;
}node[400009];
void build(int ll,int rr,int n)
{
node[n].l=ll;
node[n].r=rr;
node[n].hou=0;
if(ll==rr)
{
node[n].all=0;
}
if (ll==rr) return ;
int mid=(ll+rr)>>1;
build(ll,mid,n+n);
build(mid+1,rr,n+n+1);
node[n].all=node[n+n].all+node[n+n+1].all;
}
void updata(int ll,int rr,int a,int n)
{
if (ll<=node[n].l&&node[n].r<=rr&&node[n].hou!=-1)
{
node[n].hou+=a;
node[n].all+=(node[n].r-node[n].l+1)*a;
return ;
}
if(node[n].hou)
{
node[n+n].hou+=node[n].hou;
node[n+n].all+=(node[n+n].r-node[n+n].l+1)*node[n].hou;
node[n+n+1].hou+=node[n].hou;
node[n+n+1].all+=(node[n+n+1].r-node[n+n+1].l+1)*node[n].hou;
node[n].hou=0;
}
int mid=(node[n].l+node[n].r)>>1;
if (rr<=mid) updata(ll,rr,a,n+n);
else if (ll>=mid+1) updata(ll,rr,a,n+n+1);
else
{
updata(ll,mid,a,n+n);
updata(mid+1,rr,a,n+n+1);
}
node[n].all=node[n+n].all+node[n+n+1].all;
}
int search(int ll,int rr,int n)
{
if(node[n].l==ll&&node[n].r==rr)
{
return node[n].all;
}
if(node[n].hou)
{
node[n+n].hou+=node[n].hou;
node[n+n].all+=(node[n+n].r-node[n+n].l+1)*node[n].hou;
node[n+n+1].hou+=node[n].hou;
node[n+n+1].all+=(node[n+n+1].r-node[n+n+1].l+1)*node[n].hou;
node[n].hou=0;
}
int mid=(node[n].l+node[n].r)>>1;
if (rr<=mid) return search(ll,rr,n+n);
else if (ll>mid) return search(ll,rr,n+n+1);
else
{
return search(ll,mid,n+n)+search(mid+1,rr,n+n+1);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,add=0,ll,rr;
for(i=0;i<n;i++)
{
scanf("%d%d",&ll,&rr);
s[add].c=ll;
s[add].no=add;
add++;
s[add].c=rr;
s[add].no=add;
add++;
}
sort(&s[0],&s[add],cmp);
int dd=0;
s[0].temp=0;
for(i=1;i<add;i++)
{
if(s[i].c==s[i-1].c)
s[i].temp=dd;
else
{
dd++;
s[i].temp=dd;
}
}
sort(&s[0],&s[add],cmp1);
int j;
build(0,dd,1);
for(i=0;i<add;i+=2)
{
updata(s[i].temp,s[i+1].temp,1,1);
}
int max=0;
for(i=0;i<dd;i++)
{
if(search(i,i,1)>max)
max=search(i,i,1);
}
printf("%d\n",max);
}
}
更简单的方法
看了一下别人的解法,是优先队列
先按开始时间排序,在不断更新队列,同时记录队列什么时候最长就好了
#include<stdio.h>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
struct data
{
int start,end;
}s[50009];
int cmp(data a,data b)
{
return a.start<b.start;
}
struct qq
{
friend bool operator<(qq a,qq b)
{
return a.end>b.end;
}
qq(int a)
{
end=a;
}
int end;
};
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i;
for(i=0;i<n;i++)
{
scanf("%d%d",&s[i].start,&s[i].end);
}
sort(&s[0],&s[n],cmp);
int max=1;
priority_queue<qq> pq;
pq.push(qq(s[0].end));
for(i=1;i<n;i++)
{
while((!pq.empty())&&pq.top().end<s[i].start)
pq.pop();
pq.push(qq(s[i].end));
if(pq.size() > max)max=pq.size();
}
printf("%d\n",max);
}
}