BZOJ 2402 陶陶的难题II

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88259273

陶陶不要给我出难题啊。。。。。。
在这里插入图片描述
套路分数规划+线段树+凸包二分。
sb错误不断。

AC Code:

#include<bits/stdc++.h>
#define maxn 30005
#define lc now<<1
#define rc now<<1|1
#define inf 0x3f3f3f3f
#define eps 1e-4
using namespace std;

int n;
double x[maxn],y[maxn],p[maxn],q[maxn];
int info[maxn],Prev[maxn<<1],to[maxn<<1],cnt_e;
inline void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }

int fa[maxn],dep[maxn],siz[maxn],son[maxn],tp[maxn],id[maxn],pos[maxn],tot,cnt_l;

void dfs1(int now,int ff)
{
	dep[now] = dep[fa[now] = ff] + 1;
	siz[now] = 1 , son[now] = -1;
	for(int i=info[now];i;i=Prev[i])
		if(to[i]!=ff)
		{
			dfs1(to[i],now);
			siz[now] += siz[to[i]];
			if(son[now] == -1 || siz[to[i]] > siz[son[now]])
				son[now] = to[i];
		}
}

void dfs2(int now,int ff)
{
	pos[id[now] = ++tot] = now;
	if(son[now]!=-1) tp[son[now]] = tp[now] , dfs2(son[now],now);
	for(int i=info[now];i;i=Prev[i])
		if(to[i]!=ff && to[i]!=son[now])
		{
			tp[to[i]] = to[i];
			dfs2(to[i],now);
		}
}

struct Point
{
	double x,y;
	Point (double x=0,double y=0):x(x),y(y){}
	Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
	double operator *(const Point &B)const{ return x*B.y-y*B.x; }
	bool operator <(const Point &B)const{ return x == B.x ? y < B.y : x < B.x; }
}arr[maxn];

vector<Point>G[maxn<<2][2];
void build(int now,int l,int r)
{
	int cnt = 0;
	for(int i=l;i<=r;i++) arr[++cnt] = Point(x[pos[i]],y[pos[i]]);
	sort(arr+1,arr+1+cnt);
	vector<Point>&h = G[now][0];
	for(int i=1,siz=0;i<=cnt;i++) 
	{
		for(;siz>=2 && (arr[i]-h[siz-1])*(h[siz-1]-h[siz-2])<=0;siz--,h.pop_back());
		h.push_back(arr[i]),siz++;//!!!
	}
	cnt = 0;
	for(int i=l;i<=r;i++) arr[++cnt] = Point(p[pos[i]],q[pos[i]]);
	sort(arr+1,arr+1+cnt);
	vector<Point>&g = G[now][1];
	for(int i=1,siz=0;i<=cnt;i++) 
	{
		for(;siz>=2 && (arr[i]-g[siz-1])*(g[siz-1]-g[siz-2])<=0;siz--,g.pop_back());
		g.push_back(arr[i]),siz++;
	}
	
	if(l == r) return;
	int mid = (l+r) >> 1;
	build(lc,l,mid),build(rc,mid+1,r);
}


bool flag = 0;

double Max[2];

void ser(vector<Point>&p,Point base,double &num)
{
	
	if(p.size() == 0) return;
	if(p.size() == 1) { num = max(num, p[0].y - p[0].x * base.y); return;}
	int L = 1 , R = p.size() - 1 , mid;
	for(;L<R;)
	{
		int mid = (L+R+1) >> 1;
		if((p[mid]-p[mid-1]) * base >= 0) R = mid-1;
		else L = mid;
	}
	if((p[L]-p[L-1]) * base >= 0) L--;	
	num = max( num , p[L].y - p[L].x * base.y);
}

void check(int now,double K)
{
	Point base = Point(1,K);
	ser(G[now][0],base,Max[0]);
	ser(G[now][1],base,Max[1]);
}

void Query(int now,int l,int r,int ql,int qr,double K)
{
	if(ql > r || qr < l) return;
	if(ql <= l && r <= qr) 
	{
		check(now,K);
		return;
	}
	int mid = (l+r) >> 1;
	Query(lc,l,mid,ql,qr,K),Query(rc,mid+1,r,ql,qr,K);
}

int main()
{
	scanf("%d",&n);
	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++) 
	{
		int u,v;
		scanf("%d%d",&u,&v);
		Node(u,v),Node(v,u);
	}
	
	dfs1(1,0),tp[1]=1,dfs2(1,0);

	build(1,1,n);
	
	int M;
	scanf("%d",&M); 
	for(int i=0;i<M;i++)
	{
		int a,b,c,d;
		scanf("%d%d",&a,&b),c=a,d=b;
		double L = 0 , R = 1e8 , mid;
		while(L<R-eps)
		{
			mid = (L+R) * 0.5;
			Max[1] = Max[0] = -inf;
			a=c,b=d;
			for(;tp[a]!=tp[b];)
			{
				if(dep[tp[a]] > dep[tp[b]]) swap(a,b);
				Query(1,1,n,id[tp[b]],id[b],mid);
				b = fa[tp[b]];
			}
			if(dep[a] > dep[b]) swap(a,b);
			Query(1,1,n,id[a],id[b],mid);
			if(Max[0] + Max[1] >= 0) L = mid;
			else R = mid - eps;      
		}
		
		printf("%.4lf\n",L);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88259273
今日推荐