【BZOJ 2402】陶陶的难题II(分数规划+树链剖分+凸包二分)

传送门

题解已经写在标题上了

不过复杂度O(nlog4n)O(nlog^4n)能过也是神了

#include<bits/stdc++.h>
using namespace std;
const int RLEN=(1<<20)|5;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
	return f?res:-res;
}
#define pb push_back
#define re register
#define fi first
#define se second
#define pii pair<int,int>
#define cs const
#define bg begin
#define ll long long
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=30005;
char xxx;
cs double eps=1e-7;
struct pt{
	double x,y;
	pt(double a=0,double b=0):x(a),y(b){}
	friend inline pt operator -(cs pt &a,cs pt &b){
		return pt(a.x-b.x,a.y-b.y);
	}
	friend inline double operator *(cs pt &a,cs pt &b){
		return a.x*b.y-a.y*b.x;
	}
	friend inline bool operator <(cs pt &a,cs pt &b){
		return a.x==b.x?a.y<b.y:a.x<b.x;
	}
	inline double K(){
		return y/x;
	}
};
int idx[N];
double x[N],y[N],p[N],q[N];
pt qq[N];
inline vector<pt> gettb(vector<pt> tt){
	sort(tt.bg(),tt.end());
	int top=0;qq[top=1]=tt[0];
	for(int i=1;i<tt.size();i++){
		while(top>1&&(qq[top]-qq[top-1])*(tt[i]-qq[top-1])>=0)top--;
		qq[++top]=tt[i];
	}
	vector<pt> now;
	for(int i=1;i<=top;i++)now.pb(qq[i]);
	return now;
}
inline double ask(cs vector<pt> &tt,double k){
	int l=1,r=tt.size()-1,res=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if((tt[mid]-tt[mid-1]).K()>=k)l=mid+1,res=mid;
		else r=mid-1;
	}
	return tt[res].y-tt[res].x*k;
}
struct data{
	double a,b;
	data(double _a=0,double _b=0):a(_a),b(_b){}
	friend inline data operator +(cs data &a,cs data &b){
		return data(max(a.a,b.a),max(a.b,b.b));
	}
};
namespace Seg{
	vector<pt> tr[2][N<<2];
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	void build(int u,int l,int r){
		vector<pt>now;
		for(int i=l;i<=r;i++)now.pb(pt(x[idx[i]],y[idx[i]]));
		tr[0][u]=gettb(now);now.clear();
		for(int i=l;i<=r;i++)now.pb(pt(p[idx[i]],q[idx[i]]));
		tr[1][u]=gettb(now);
		if(l==r)return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	data query(int u,int l,int r,int st,int des,double k){
	//	cerr<<u<<" "<<l<<" "<<r<<" "<<st<<" "<<des<<'\n';
		if(st<=l&&r<=des)return data(ask(tr[0][u],k),ask(tr[1][u],k));
		if(des<=mid)return query(lc,l,mid,st,des,k);
		if(st>mid)return query(rc,mid+1,r,st,des,k);
		return query(lc,l,mid,st,des,k)+query(rc,mid+1,r,st,des,k);
	}
	#undef lc
	#undef rc
	#undef mid
}
vector<int> e[N];
int in[N],dfn,siz[N],son[N],top[N],fa[N],dep[N];
int n,m;
double mx;
void dfs1(int u){
	siz[u]=1;
	for(int &v:e[u]){
		if(v==fa[u])continue;
		fa[v]=u,dep[v]=dep[u]+1;
		dfs1(v),siz[u]+=siz[v];
		if(siz[v]>siz[son[u]])son[u]=v;
	}
}
void dfs2(int u,int tp){
	top[u]=tp,in[u]=++dfn,idx[dfn]=u;
	if(son[u])dfs2(son[u],tp);
	for(int &v:e[u]){
		if(v==fa[u]||v==son[u])continue;
		dfs2(v,v);
	}
}
inline double pathquery(int u,int v,double k){
	data now(-1e9,-1e9);
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		now=now+Seg::query(1,1,n,in[top[u]],in[u],k);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v])swap(u,v);
	now=now+Seg::query(1,1,n,in[v],in[u],k);
	return now.a+now.b;
}
char yyy;
int main(){
	n=read();
	for(int i=1;i<=n;i++)scanf("%lf",&x[i]);
	for(int i=1;i<=n;i++)scanf("%lf",&y[i]);
	for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
	for(int i=1;i<=n;i++)scanf("%lf",&q[i]);
	for(int i=1;i<=n;i++)chemx(mx,y[i]/x[i]),chemx(mx,q[i]/p[i]);
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		e[u].pb(v),e[v].pb(u);
	}
	dep[1]=1,dfs1(1),dfs2(1,1);
	Seg::build(1,1,n);
	m=read();
	for(int i=1;i<=m;i++){
		int a=read(),b=read();
		double l=0,r=mx;
		while(l+eps<r){
			double mid=(l+r)*0.5;
			if(pathquery(a,b,mid)>=0)l=mid;
			else r=mid;
		}
		printf("%.4lf\n",l);
	}
}
posted @ 2019-10-19 00:06  Stargazer_cykoi  阅读(137)  评论(0编辑  收藏  举报