链接:https://vjudge.net/problem/UVA-1398
思路: 一开始拿到题目就想到用数学公式强行算出进入左端点的时间,出去的时间,然后还要和零比较,后面看了刘汝佳的写法才发现还可以写的这么简单。原来我是建的一个区间结构,将开始和结尾时间都放进去,然后用一个优先级队列去维护右端点结构,每次到左端点记录时就将队列中在这个时间之前的右端点(包括闭区间)全部pop出去,记录这个左端点并更新最大值后再将他的右端点放入队列中。今天学到了一种新的写法,就是把左右端点拆开,遇到左端点就将当前数目+1并更新最大值,遇到最右端点就将当前数目减1,这样避免了左右端点在一起时只能拿一边排序从而需要用队列维护另一边的尴尬局面。妙不可言!!!
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
struct Event{
double t;
int type;
Event(){}
Event(double tt,int typee){
t = tt;
type = typee;
}
bool operator<(const Event &a1)const{
return t<a1.t||(t==a1.t&&type>a1.type);
}
}ess[200001];
int t,n,w,h,x,y,a,b;
void update(int x,int w,int a,double &l,double &r){
if(a==0){
if(x>=w||x<=0)r = l-1;//无解
}
else if(a>0){
l = max(l,-(double)x/a);
r = min(r,(double)(w-x)/a);
}
else{
l = max(l,(double)(w-x)/a);
r = min(r,-(double)x/a);
}
}
int main(){
scanf("%d",&t);
while(t--){
int e = 0;
scanf("%d%d%d",&w,&h,&n);
for(int i=0;i<n;++i){
double l = 0,r = 1e9;
scanf("%d%d%d%d",&x,&y,&a,&b);
update(x,w,a,l,r);//更新左端点的边
update(y,h,b,l,r);//更新右端点的边
if(l<r){
ess[e++] = Event(l,0);
ess[e++] = Event(r,1);
}
}
sort(ess,ess+e);
int res = 0;
int ans = 0;
for(int i=0;i<e;i++){
if(ess[i].type==0){
ans++;
res = max(res,ans);
}
else ans--;
}
printf("%d\n",res);
}
return 0;
}
网友评论