其他分享
首页 > 其他分享> > bzoj 3116 登顶计划题解

bzoj 3116 登顶计划题解

作者:互联网

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
struct vec{
	long double x,y;
	long double operator * (vec oth){
		return x*oth.y-y*oth.x;
	}
	vec operator - (vec oth){
		return vec{x-oth.x,y-oth.y};
	}
	vec operator + (vec oth){
		return vec{x+oth.x,y+oth.y};
	}
};
bool cmp(vec A,vec B){
	return A.x<B.x;
}
const int MAXN=2e5+233;
const long double eps=1e-7;
int n;
vec a[MAXN];
int sz;
vec sta[MAXN];
int sta2[MAXN];
vector<vec> ip;
void cross(vec A,vec B,vec C,vec D){
	long double k=(A.y-B.y)/(A.x-B.x);
	long double b=A.y-A.x*k;
	long double k2,b2;
	k2=(C.y-D.y)/(C.x-D.x);
	b2=C.y-C.x*k2;
	long double x,y;
	if(abs(k-k2)<eps) return;
	if(C.x>D.x) swap(C,D);
	x=(b2-b)/(k-k2);
	y=x*k+b;
	if(x+eps<D.x&&x-eps>C.x){
		ip.PB(vec{x,y});
	}
}
int le[MAXN],ri[MAXN],id[MAXN];
long double tar[MAXN];
bool equ(vec A,vec B){
	return abs(A.x-B.x)<eps&&abs(A.y-B.y)<eps;
}
vector<int> g[MAXN];
long double dis[MAXN];
long double rest[MAXN];
long double get(int u,int v){
	if(u>v) swap(u,v);
	return dis[v]-dis[u];
}
void dfs(int now){
	for(auto it:g[now]){
		rest[it]=rest[now]+get(it,now); 
		dfs(it);
	}
}
int main(){
	scanf("%d",&n);
	rb(i,1,n) scanf("%Lf%Lf",&a[i].x,&a[i].y);
	sz=0;
	rb(i,1,n) ip.PB(a[i]);
	rb(i,1,n){
		while(sz>=2&&(sta[sz-1]-sta[sz])*(a[i]-sta[sz])<eps) {
			cross(sta[sz-1],sta[sz],a[i-1],a[i]);
			--sz;
		}
		sta[++sz]=a[i];
	}
	sz=0;
	rl(i,n,1){
		while(sz>=2&&(sta[sz-1]-sta[sz])*(a[i]-sta[sz])>-eps) {
			cross(sta[sz-1],sta[sz],a[i+1],a[i]);
			--sz;
		}
		sta[++sz]=a[i];
	}
	sort(ALL(ip),cmp);
	vector<vec> v;
	vec last=vec{INF,INF};
	for(auto it:ip){
		if(equ(last,it)){
			continue;
		}
		last=it;
		v.PB(it);
	}
	int m=v.size();
	int to=1;
	rep(i,m){
		while(to<=n&&a[to].x+eps<v[i].x)++to;
		if(to<=n&&equ(a[to],v[i])) id[to]=i;
	}
	rep(i,m){
//		printf("(%.6Lf %.6Lf)\n",v[i].x,v[i].y);
		le[i]=ri[i]=i;
		tar[i]=v[i].y;
	}
	sz=0;
	rep(i,m){
		while(sz>=2&&(sta[sz-1]-sta[sz])*(v[i]-sta[sz])<eps) {--sz;}
		if(sz>=1&&sta[sz].y>v[i].y) le[i]=sta2[sz],tar[i]=sta[sz].y;
		sta[++sz]=v[i];
		sta2[sz]=i;
	}
	sz=0;
	rl(i,m-1,0){
		while(sz>=2&&(sta[sz-1]-sta[sz])*(v[i]-sta[sz])>-eps) {--sz;}
		if(sz>=1&&sta[sz].y>v[i].y){
			ri[i]=sta2[sz];
			if(v[ri[i]].y>tar[i]) tar[i]=v[ri[i]].y;
//			cout<<i<<endl;
		}
		sta[++sz]=v[i];
		sta2[sz]=i;
	}
	int root=0;
	rep(i,m){
		if(ri[i]==le[i]) root=i;
	}
	stack<pair<long double ,int> > stk;
	rep(i,m){
		if(i==root) continue;
		while(!stk.empty()&&stk.top().FIR<=tar[i]+eps){stk.pop();}
		if(v[le[i]].y>v[ri[i]].y){
			if(stk.empty()||stk.top().SEC<=le[i]) g[le[i]].PB(i);
			else g[stk.top().SEC].PB(i); 
		}
		stk.push(II(tar[i],i));
	}
	while(!stk.empty()) stk.pop();
	rl(i,m-1,0){
		if(i==root) continue;
		while(!stk.empty()&&stk.top().FIR<=tar[i]+eps){stk.pop();}
		if(v[ri[i]].y>=v[le[i]].y){
			if(stk.empty()||stk.top().SEC>=ri[i]) g[ri[i]].PB(i);
			else g[stk.top().SEC].PB(i); 
		}
		stk.push(II(tar[i],i));
	}
//	rep(i,m){
//		cout<<le[i]<<' '<<ri[i]<<' ';
//		printf("%.6Lf\n",tar[i]);
//	}
	rb(i,1,m){
		double X,Y;
		X=v[i].x-v[i-1].x;
		Y=v[i].y-v[i-1].y;
		X=X*X;
		Y=Y*Y;
		dis[i]=sqrt(X+Y);
		dis[i]+=dis[i-1];
	}
	rest[root]=0;
	dfs(root);
	rb(i,1,n){
		printf("%.6Lf\n",rest[id[i]]);
	}
	return 0;
}

标签:oth,sz,sta,题解,long,double,vec,3116,bzoj
来源: https://www.cnblogs.com/gary-2005/p/14396906.html