[CodeChef Trips]Children Trips

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodeChef Trips]Children Trips相关的知识,希望对你有一定的参考价值。

Children Trips

题解

关于这种跳跃的**题,当它 P P P值很大时几次就可以跳到目标节点了,而较小时却会跳很久,所以我们很快就可以想到对询问分类处理。

对于 P > n P>\\sqrt{n} P>n 的询问,它跳到终点的次数大概是 n \\sqrt{n} n 级别的,我们可以直接用它暴力跳,用倍增维护它下一个可以跳到的节点。
很明显,这样单次询问的时间复杂度是 O ( n l o g   n ) O\\left(\\sqrt{n}log\\,n\\right) O(n logn)

而对于 P ⩽ n P\\leqslant \\sqrt{n} Pn 询问,因为这样的 P P P的数量很小,我们不妨考虑预处理出这些 P P P的倍增数组,即它跳 2 k 2^k 2k步可以跳到哪里,询问时就直接倍增找答案。
很明显,这样的预处理时间复杂度是 O ( n n l o g   n ) O\\left(n\\sqrt{n}log\\,n\\right) O(nn logn)的,单次询问时间复杂度为 O ( l o g   n ) O\\left(log\\,n\\right) O(logn)

虽然对于第二类的询问我们只能从两端开始跳,而从上往下跳与从下往上跳两种方法的到的答案不一定相同,但由于它的边权最大是 2 2 2,所以我们整个过程中浪费也只会浪费 1 1 1的跳跃。
可以发现,这并不影响我们得到正确答案。

时间复杂度很明显是 O ( ( n + q ) n l o g   n ) O\\left((n+q)\\sqrt{n}log\\,n\\right) O((n+q)n logn)

源码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=1000000000000000000LL;
const int mo=1e9+7;
const int n1=300;
const int inv2=499122177;
const int jzm=2333;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-7;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,head[MAXN],tot,dep[MAXN],dis[MAXN],f[MAXN][20],fw[MAXN][20];
int ord[MAXN],idx,totmin,totmax,ans[MAXN];
struct edge{int to,nxt,paid;}e[MAXN<<1];
struct ming{int u,v,p,id;}smin[MAXN],smax[MAXN];
vector<int>vec[305];
void addEdge(int u,int v,int w){e[++tot]=(edge){v,head[u],w};head[u]=tot;}
void dosaka(int u,int fa){
	dep[u]=dep[fa]+1;f[u][0]=fa;ord[++idx]=u;
	for(int i=1;i<=18;i++)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;if(v==fa)continue;
		dis[v]=dis[u]+e[i].paid;dosaka(v,u);
	}
}
int lca(int a,int b){
	if(dep[a]>dep[b])swap(a,b);
	for(int i=18;i>=0;i--)if(dep[f[b][i]]>=dep[a])b=f[b][i];
	if(a==b)return a;
	for(int i=18;i>=0;i--)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
	return f[a][0];
}
signed main(){
	read(n);
	for(int i=1;i<n;i++){
		int u,v,w;read(u);read(v);read(w);
		addEdge(u,v,w);addEdge(v,u,w);
	}
	dosaka(1,0);read(m);
	for(int i=1;i<=m;i++){
		int s,f,p;read(s);read(f);read(p);
		if(p<=n1)smin[++totmin]=(ming){s,f,p,i};
		else smax[++totmax]=(ming){s,f,p,i};
	}
	for(int i=1;i<=totmin;i++)vec[smin[i].p].push_back(i);
	for(int i=2;i<=n1;i++){
		if(vec[i].empty())continue;
		for(int j=1;j<=n;j++){
			int x=ord[j],now=x;
			for(int k=18;k>=0;k--)
				if(dis[x]-dis[f[now][k]]<=i)now=f[now][k];
			fw[x][0]=now;
			for(int k=1;k<=18;k++)fw[x][k]=fw[fw[x][k-1]][k-1];
		}
		for(int j=0;j<vec[i].size();j++){
			int t=vec[i][j],u=smin[t].u,v=smin[t].v,u_v=lca(u,v),x=v;
			for(int k=18;k>=0;k--)if(dep[fw[u][k]]>dep[u_v])
				u=fw[u][k],ans[smin[t].id]+=(1<<k);
			for(int k=18;k>=0;k--)if(dep[fw[v][k]]>dep[u_v])
				v=fw[v][k],ans[smin[t].id]+=(1<<k);
			ans[smin[t].id]+=(dis[u]+dis[v]-2*dis[u_v]+i-1)/i;
		} 
	}
	for(int i=1;i<=totmax;i++){
		int u=smax[i].u,v=smax[i].v,u_v=lca(u,v),w=smax[i].p,x=v; 
		if(u==v)continue;
		while(dis[u]-dis[以上是关于[CodeChef Trips]Children Trips的主要内容,如果未能解决你的问题,请参考以下文章

262. Trips and Users (Hard)

LeetCode 2187. Minimum Time to Complete Trips

[LeetCode] 262. Trips and Users 旅行和用户

codechefChildren Trips

codeforces 1037E. Trips(倒叙)

CODECHEFChildren Trips 倍增