zoukankan      html  css  js  c++  java
  • bzoj 3190 [JLOI2013]赛车 半平面交+细节处理

    题目大意

    这里有一场赛车比赛正在进行,赛场上一共有N辆车,分别称为g1,g2……gn。赛道是一条无限长的直线。最初,gi位于距离起跑线前进ki的位置。比赛开始后,车辆gi将会以vi单位每秒的恒定速度行驶。在这个比赛过程中,如果一辆赛车曾经处于领跑位置的话(即没有其他的赛车跑在他的前面),这辆赛车最后就可以得奖,而且比赛过程中不用担心相撞的问题。现在给出所有赛车的起始位置和速度,你的任务就是算出那些赛车将会得奖。

    分析

    一辆车的函数就是(f_i(x)=k_i x +b_i)
    那题目就是要使得有一时刻(f_i(x))下面有所有(f_j(x))
    那么就有一个性质:
    一向量(x)在某段时间在另一向量(y)的左边,那么这段时间(x)领先
    那么就有曾经领先在所有车前面的赛车
    它的函数出现在半平面交上

    注意

    细节挺多的
    1.函数中有一个点在半平面交上也算进答案
    2.重边要特判
    所以先排好序,算好重边,加个vector,再跑半平面交,比较好写些

    solution

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef double db;
    const int M=10007;
    
    inline int rd(){
    	int x=0;;bool f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-')f=0;
    	for(;isdigit(c);c=getchar()) x=x*10+c-48;
    	return f?x:-x;
    }
    
    struct pt{
    	db x,y;
    	pt(db xx=0.0,db yy=0.0){x=xx;y=yy;}
    };
    pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
    pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
    pt operator *(pt x,db d){return pt(x.x*d,x.y*d);}
    pt operator /(pt x,db d){return pt(x.x/d,x.y/d);}
    db dot(pt x,pt y){return x.x*y.x+x.y*y.y;}
    db det(pt x,pt y){return x.x*y.y-x.y*y.x;}
    db len(pt x){return sqrt(dot(x,x));}
    db dis(pt x,pt y){return len(y-x);}
    db area(pt x,pt y,pt z){return det(y-x,z-x);}
    
    struct line{
    	pt P,v;
    	int cnt;
    	line(pt PP=pt(),pt vv=pt(),int cc=0){P=PP;v=vv;cnt=cc;}
    }l[M],s[M];
    int top;
    bool ptright(pt x,line y){return det(y.v,x-y.P)<0;}//<0因为在半平面上的点也能算进答案里面
    bool parallel(line x,line y){return det(x.v,y.v)==0;}
    pt inter(line x,line y){
    	pt u=x.P-y.P;
    	db t=det(u,y.v)/det(y.v,x.v);
    	return x.P+x.v*t;
    }
    
    struct pai{int k,b,id;}a[M];
    bool operator ==(pai x,pai y){return x.k==y.k&&x.b==y.b;}
    bool operator !=(pai x,pai y){return !(x==y);}
    
    bool cmp(pai x,pai y){
    	if(x.k!=y.k)return x.k<y.k;
    	return x.b<y.b;
    }
    
    int n,m;
    vector<int>g[M];
    int ps[M];
    int ans=0;
    int out[M];
    
    void hpi(){
    	top=0;
    	for(int i=1;i<=m;i++){
    		while(top>1&&ptright(inter(s[top-1],s[top]),l[i])) top--;
    		s[++top]=l[i];ps[top]=i;
    	}
    }
    
    int main(){
    	int i,j;
    	n=rd();
    	for(i=1;i<=n;i++) a[i].b=rd();
    	for(i=1;i<=n;i++) a[i].k=rd();
    	for(i=1;i<=n;i++) a[i].id=i;
    	sort(a+1,a+n+1,cmp);
    	l[m=1]=line(pt(0,0),pt(0,-1),0);
    	for(i=1;i<=n;i++){
    		if(i==1||a[i]!=a[i-1]) l[++m]=line(pt(0,a[i].b),pt(1,a[i].k),0);
    		l[m].cnt++;
    		g[m].push_back(a[i].id);
    	}
    	hpi();
    	int tot=0;
    	for(i=1;i<=top;i++){
    		ans+=s[i].cnt;
    		for(j=0;j<g[ps[i]].size();j++) out[++tot]=g[ps[i]][j];
    	}
    	sort(out+1,out+tot+1);
    	printf("%d
    ",ans);
    	for(i=1;i<tot;i++) printf("%d ",out[i]);
    	printf("%d
    ",out[tot]);
    	return 0;
    }
    
  • 相关阅读:
    harbor无法登陆解决
    k8s中使用harbor
    harbor扩容
    harbor设置开机自启
    设置开机自启
    关Java的内存模型(JMM)
    多线程相关概念
    多线程(JDK1.5的新特性互斥锁)
    synchronized关键字
    【异常】redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'PSETEX'
  • 原文地址:https://www.cnblogs.com/acha/p/6485022.html
Copyright © 2011-2022 走看看