• Jzoj4877 力场护盾(红警系列)


    ZMiG成功粉碎了707的基因突变计划,为了人类的安全,他决定向707的科学实验室发起进攻!707并没有想到有人敢攻击她的实验室,一时间不知所措,决定牺牲电力来换取自己实验室的平安。
        在实验室周围瞬间产生了一个无限大的力场护盾,它看上去无懈可击!不过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]);
    }

  • 相关阅读:
    Pyechart——学习
    matplotlib——散点图、条形图、直方图
    matplotlib——折线图
    寻找n以内的亲密数对
    Golang判断时间点处于今天
    寒假作业3
    寒假作业2
    面向对象程序设计寒假作业1
    自我介绍
    关于cve2019_0708的反弹shell
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7774318.html
Copyright © 2020-2023  润新知