在实验室周围瞬间产生了一个无限大的力场护盾,它看上去无懈可击!不过ZMiG拥有惊人的双向观察能力,经过他的反复观察,找到了这个护盾的N个弱点,他本想逐一击破,却发现一股神秘力量阻止了他的行为。原来他身处力场之中,受到了两股神秘力量的影响,这两股力量来自两个不同的方向并形成了一个小于180度的角,ZMiG每次可攻击的范围都受到这两个力的影响,当他攻击了点X之后,下一次可以攻击的点必须在以X为坐标原点的情况下,这两个力方向的夹角之间(包含边界)(具体意思可看样例)
ZMiG当然想打出一串最长的Combo,所以他想问问你最多可以攻击707弱点多少次
这道题需要一点点向量的知识,让后就可以实现坐标系之间的转换了
设两个向量为 (x1,y1) (x2,y2)
那么一个点 (x,y) 在新的坐标系的映射(x',y')里就满足以下方程
x'(x1,y1)+y'(x2,y2)=(x,y)
解方程即可得到x'和y'
但是坑点是精度问题,这道题要用数据结构来维护而且排序的时候也要考虑精度问题
比如,原本本地AC的code是这样的:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define D double
#define mid (l+r>>1)
using namespace std;
struct dt{ D a,b; } s[200010];
int n,m,r[200010],w[800080],f[200010];
D x1,y1,x2,y2,c1,c2,v[200010];
inline bool cmp(dt a,dt b){ return a.a<b.a; }
void update(int l,int r,int x,int p,int k){
if(l==r){ w[x]=max(w[x],k); return; }
if(p<=mid) update(l,mid,x<<1,p,k);
else update(mid+1,r,x<<1|1,p,k);
w[x]=max(w[x<<1],w[x<<1|1]);
}
int query(int l,int r,int x,int L,int R){
if(L<=l && r<=R) return w[x];
int Ans=0;
if(L<=mid) Ans=max(Ans,query(l,mid,x<<1,L,R));
if(mid<R) Ans=max(Ans,query(mid+1,r,x<<1|1,L,R));
return Ans;
}
int main(){
freopen("shield.in","r",stdin);
freopen("shield.out","w",stdout);
scanf("%d",&n);
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
for(int i=1;i<=n;++i){
scanf("%lf%lf",&c1,&c2);
s[i]=(dt){(c1*y2-c2*x2)/(x1*y2-y1*x2),(c1*y1-c2*x1)/(y1*x2-x1*y2)};
}
sort(s+1,s+1+n,cmp);
for(int i=1;i<=n;++i) v[i]=s[i].b;
sort(v+1,v+1+n);
for(int i=1;i<=n;++i) r[i]=lower_bound(v+1,v+1+n,s[i].b)-v;
for(int i=1;i<=n;++i){ f[i]=query(0,n,1,0,r[i])+1; update(0,n,1,r[i],f[i]); }
printf("%d
",w[1]);
}
但是被精度卡剩60pts
所以必须这样写:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define D double
#define mid (l+r>>1)
using namespace std;
struct dt{ D a,b; int r; } s[200010];
int n,m,w[800080],f[200010];
D x1,Y1,x2,y2,c1,c2;
inline bool cmp(dt a,dt b){ return fabs(a.a-b.a)<10e-7?a.r<b.r:a.a<b.a; }
inline bool cmp2(dt a,dt b){ return a.b<b.b; }
void update(int l,int r,int x,int p,int k){
if(l==r){ w[x]=max(w[x],k); return; }
if(p<=mid) update(l,mid,x<<1,p,k);
else update(mid+1,r,x<<1|1,p,k);
w[x]=max(w[x<<1],w[x<<1|1]);
}
int query(int l,int r,int x,int L,int R){
if(L<=l && r<=R) return w[x];
int Ans=0;
if(L<=mid) Ans=max(Ans,query(l,mid,x<<1,L,R));
if(mid<R) Ans=max(Ans,query(mid+1,r,x<<1|1,L,R));
return Ans;
}
int main(){
freopen("shield.in","r",stdin);
freopen("shield.out","w",stdout);
scanf("%d",&n);
scanf("%lf%lf%lf%lf",&x1,&Y1,&x2,&y2);
for(int i=1;i<=n;++i){
scanf("%lf%lf",&c1,&c2);
s[i]=(dt){(D)(c1*y2-c2*x2)/(x1*y2-Y1*x2),(D)(c1*Y1-c2*x1)/(Y1*x2-x1*y2)};
}
sort(s+1,s+1+n,cmp2);
for(int i=1;i<=n;++i) s[i].r=s[i].b-s[i-1].b<10e-7?s[i-1].r:s[i-1].r+1;
sort(s+1,s+1+n,cmp);
for(int i=1;i<=n;++i){ f[i]=query(0,n,1,0,s[i].r)+1; update(0,n,1,s[i].r,f[i]); }
printf("%d
",w[1]);
}