3700: 发展城市

这题需要大量的lca,预处理是可以,但是会写死,因此采用rmq。
先学会如何求两个路径[a,b],[c,d]的交。
只要分别求c,d到[a,b]距离最近的点[u,v],然后判u,v是否在[c,d]上即可。下面以用c求u为例。
r<-lca(a,b)
if lca(r,c)!=r then u<-r
else if lca(a,c)!=r then u<-lca(a,c)
else u<-lca(b,c)
然后检验。
r<-lca(c,d)
u∈[c,d]当且仅当u在r的子树中(lca(u,r)==r)且lca(c,u)与lca(d,u)中有一个为u
同理求出并检验v
然后分类讨论。设s1、t1为[a,b]上的那个人到达、离开[u,v]的时间,s2、t2同理。
3700: 发展城市_第1张图片
然后由于这些数是浮点数(被v除过了),精度抖来抖去很麻烦,就把分母都乘到对面去,但要记得开long long !
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pii pair
#define mkp make_pair
#define X first
#define Y second
#define N 100005
#define NN 1005
#define inf 10000000
LL n,m,A[NN],B[NN],V[NN],ans;
LL he[N],ne[N<<1],W[N<<1],to[N<<1],tot;
LL lg[N<<1],dep[N],deep[N],phi[N<<1],id,pos[N],Min[N<<1][20];
LL read(){
	LL x=0;char ch=G;bool flg=0;
	while((ch<48||ch>57)&&ch!=45)ch=G;
	if(ch==45)flg=1,ch=G;
	for(;ch>47&&ch<58;ch=G)x=x*10+ch-48;
	return flg?-x:x;
}
void add(LL x,LL y,LL z){
	to[++tot]=y;W[tot]=z;ne[tot]=he[x];he[x]=tot;
}
void DFS(LL x,LL e){
	LL y,i;dep[phi[pos[x]=++id]=x]=dep[to[e]]+1;
	for(i=he[x];i;i=ne[i])if(i!=e){
		deep[y=to[i]]=deep[x]+W[i];DFS(y,i^1);phi[++id]=x;
	}
}
LL les(LL x,LL y){
	return dep[x]y)swap(x,y);
	LL tmp=lg[y-x+1];
	return les(Min[x][tmp],Min[y-(1<getd(A[x],b))flg=1,d1=getd(A[x],b);
	if(flg)return (d1+d)*V[y]>=d2*V[x]&&(d2+d)*V[x]>=d1*V[y];
	return d1*V[y]<=d2*V[x]&&(d2+d)*V[x]<=(d1+d)*V[y]||d2*V[x]<=d1*V[y]&&(d1+d)*V[y]<=(d2+d)*V[x];
}
int main(){
	LL _,i,j,x,y,z;
	x=0;j=2;
	rep(i,3,200000){
		if(i>j)j<<=1,++x;
		 lg[i]=x;
	}
	for(_=read();_--;){
		n=read();
		memset(he,0,sizeof he);tot=1;
		rep(i,2,n){
			x=read();y=read();z=read();
			add(x,y,z);add(y,x,z);
		}
		id=0;DFS(1,0);
		per(i,id,1){
			Min[i][0]=phi[i];
			for(j=1;i+(1<

你可能感兴趣的:(BZOJ)