zoukankan      html  css  js  c++  java
  • AHOI/HNOI2017队长快跑

    一道好题&难题

    转化思想





    SOL:

    容易发现:我们一定沿着给出的点走动

    我们可以把不同方向的线抽化为两个方向,上下

    排序后,找到离自己最远的可以到达的点,即是最短(中途停留会变成折线,长度增长)

    对每一个种建立单调队列

    遇见这种情况,队首会被弹出,然后自己所在的单调队列就只剩下连线点和自己

    注:atan2返回值[-pi,pi]

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const double pi=acos(-1.0);
    const int N=1e6+4;
    struct node{
    	double x,y;int fl;
    	node(double x=0,double y=0):x(x),y(y){}
    	inline bool operator <(const node &a)const{
    		return x<a.x;
    	}
    	inline node operator -(const node &a)const{
    		return node(x-a.x,y-a.y);
    	}
    	inline double operator *(const node &a)const{
    		return x*a.y-y*a.x;
    	}
    }p[N],a[N],s,t;
    inline double dis(node a){
    	return sqrt(a.x*a.x+a.y*a.y);
    }
    int n,m,q[2][N],ql[2],qr[2],from[N];
    int main(){
    	n=read();t.x=read();t.y=read();
    	for(int i=1;i<=n;i++){
    		static double l,r,th;
    		p[i].x=read();p[i].y=read();scanf("%lf",&th);
    		l=atan2(s.y-p[i].y,s.x-p[i].x);//返回值[-pi,pi] 
    		r=atan2(t.y-p[i].y,t.x-p[i].x);
    		if(l<r)p[i].fl=(l<th&&th<r);//1为下 
    		else p[i].fl=!(r<th&&th<l);
    	}
    	sort(p+1,p+n+1);
    	a[m=1]=s;
    	for(int i=1;i<=n&&p[i].x<t.x;i++)
    		if(p[i].x>s.x)a[++m]=p[i];
    	a[++m]=t;
    	q[1][0]=q[0][0]=1;
    	for(int i=1,c,fl;i<=m;i++){
    		c=a[i].fl;fl=(c?-1:1);
    		int &l0=ql[c],&r0=qr[c],&l1=ql[c^1],&r1=qr[c^1],*q0=q[c],*q1=q[c^1]; 
    		if(l1<r1&&(a[i]-a[q1[l1]])*(a[q1[l1+1]]-a[q1[l1]])*fl>=0){
    			while(l1<r1&&(a[i]-a[q1[l1]])*(a[q1[l1+1]]-a[q1[l1]])*fl>=0)l1++;
    			q0[l0=r0=r0+1]=from[i]=q1[l1];
    		}
    		else{
    			while(l0<r0&&(a[i]-a[q0[r0-1]])*(a[q0[r0]]-a[q0[r0-1]])*fl>=0)r0--;
    			from[i]=q0[r0];
    		}
    		q0[++r0]=i;
    	}
    	double ans=0;
    	for(int i=m;i!=1;i=from[i])
    		ans+=dis(a[i]-a[from[i]]);
    	printf("%.10lf",ans);
    	return (0-0);
    }
    
  • 相关阅读:
    状态压缩DP------学习小记
    hdu 4681 string
    poj 3254 Corn Fields
    poj 3680 Intervals
    poj 1149 pigs ---- 最大流
    最大流算法----(SAP 和 EK)
    poj 2151 Check the difficulty of problems
    FTP的PORT(主动模式)和PASV(被动模式)
    json.stringify(),json.stringify()与json.parse()的区别
    css 选择器
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12526652.html
Copyright © 2011-2022 走看看