1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > [CodeChef Trips]Children Trips

[CodeChef Trips]Children Trips

时间:2021-12-12 16:42:00

相关推荐

[CodeChef Trips]Children Trips

Children Trips

题解

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

对于P>nP>\sqrt{n}P>n​的询问,它跳到终点的次数大概是n\sqrt{n}n​级别的,我们可以直接用它暴力跳,用倍增维护它下一个可以跳到的节点。

很明显,这样单次询问的时间复杂度是O(nlogn)O\left(\sqrt{n}log\,n\right)O(n​logn)。

而对于P⩽nP\leqslant \sqrt{n}P⩽n​询问,因为这样的PPP的数量很小,我们不妨考虑预处理出这些PPP的倍增数组,即它跳2k2^k2k步可以跳到哪里,询问时就直接倍增找答案。

很明显,这样的预处理时间复杂度是O(nnlogn)O\left(n\sqrt{n}log\,n\right)O(nn​logn)的,单次询问时间复杂度为O(logn)O\left(log\,n\right)O(logn)。

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

可以发现,这并不影响我们得到正确答案。

时间复杂度很明显是O((n+q)nlogn)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[u_v]>w){int y=u;for(int j=18;j>=0;j--)if(dis[u]-dis[f[y][j]]<=w&&dep[f[y][j]]>dep[u_v])y=f[y][j];ans[smax[i].id]++;u=y;}while(dis[v]-dis[u_v]>w){int y=v;for(int j=18;j>=0;j--)if(dis[v]-dis[f[y][j]]<=w&&dep[f[y][j]]>dep[u_v])y=f[y][j];ans[smax[i].id]++;v=y;}ans[smax[i].id]+=(dis[u]+dis[v]-2*dis[u_v]+w-1)/w;}for(int i=1;i<=m;i++)printf("%d\n",ans[i]);return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。