题意
给定平面上的 N N 个点其中有一些是红的 , , 其他是蓝的
现在让你找一对平行线在满足在平行线之间没有蓝点 , , 并且平行线不经过任何一个点的情况下使得被夹在平行线之间的红色点个数最多
给出的点没有三点共线的情况 , , 平行线可以不平行坐标轴
题解
做一条垂直于平行线的线然后把所有点排序后都投影到这条线上形成一个序列
那么考虑在序列上我们要求的就是最长全红子串了
这个可以用线段树直接维护 ; ; 考虑到平行线的角度会变
那么答案就是我们把这条垂线在旋转的过程中所有投影序列的答案的最大值
我们显然不能直接去旋转 , , 考虑要怎么样投影序列才会发生变化
投影序列是,那么颜色序列就是 1001, 1001 , 答案是 1 1
当投影线是时投影序列是 {1,2,3,4} { 1 , 2 , 3 , 4 }
当投影线是 L2 L 2 时投影序列是 {1,2,4,3} { 1 , 2 , 4 , 3 }
也就是说当投影线的斜率从小于两点连线垂线 (Lx) ( L x ) 斜率到大于他的过程中这两个点在投影序列上的位置会互换
因为垂线的斜率和原直线的斜率是一一对应的 , , 那么我们可以直接按照两点之间的连线的斜率排序
那么旋转投影线每次就可以直接旋转到下一个垂线的位置
即使有两点投影位置相同也没关系因为我们可以微调一下
注意对于所有斜率相同的直线我们需要一次性在线段树上处理完
因为总共有 n2 n 2 条线 , , 所以会发生次交换 , , 所以复杂度是的
Hint: H i n t :
连线的方向和转动的方向要一致(需要脑补一下)
斜率判等的精度要高一点
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c-48;
while(c=gc(),47<c&&c<58)x=x*10+c-48;x*=y;
}
const int N=1005,M=5e5+5;
const double eps=1e-15;
typedef int arr[N];
typedef double db;
struct po{
int x,y,col,id;
inline void in(){sd(x),sd(y),col=gc()=='R';}
inline bool operator<(const po b)const{return x==b.x?y<b.y:x<b.x;}
inline db operator/(const po b){return atan2(y-b.y,x-b.x);}
}p[N];
struct Li{
int a,b;db slope;
inline bool operator<(const Li T)const{return slope<T.slope;}
inline bool operator==(const Li b)const{return fabs(slope-b.slope)<eps;}
}L[M];
struct Seg{int l,r,mx,sz;}tr[N<<2];
int n,m,ans,Sz=1;
inline void up(int p,int lc,int rc){
tr[p].mx=max(tr[lc].r+tr[rc].l,max(tr[lc].mx,tr[rc].mx));
tr[p].l=tr[lc].l,tr[p].r=tr[rc].r;
if(tr[lc].l==tr[lc].sz)tr[p].l+=tr[rc].l;
if(tr[rc].r==tr[rc].sz)tr[p].r+=tr[lc].r;
}
inline void mdy(int p,int x){for(p+=Sz,tr[p]={x,x,x,1},p>>=1;p;p>>=1)up(p,p<<1,p<<1|1);}
inline void upd(Li x){
if(p[x.a].col^p[x.b].col)
mdy(p[x.b].id,p[x.a].col),
mdy(p[x.a].id,p[x.b].col);
swap(p[x.a].id,p[x.b].id);
}
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
sd(n);
fp(i,1,n)p[i].in();sort(p+1,p+n+1);
fp(i,1,n)p[i].id=i;while(Sz<=n)Sz<<=1;--Sz;
fp(i,1,n)tr[i+Sz].sz=1,p[i].col?tr[i+Sz]={1,1,1,1},1:0;
fd(i,Sz,1)tr[i].sz=tr[i<<1].sz+tr[i<<1|1].sz,up(i,i<<1,i<<1|1);
fp(i,1,n)fp(j,i+1,n)L[++m]={i,j,p[j]/p[i]};
sort(L+1,L+m+1);
fp(i,1,m){
upd(L[i]);
while(L[i]==L[i+1]&&i<m)upd(L[++i]);
cmax(ans,tr[1].mx);
}
printf("%d\n",ans);
return 0;
}