zoukankan      html  css  js  c++  java
  • 牛客 城市网络(倍增)

    这题暴力思路是一直往上跳,然后计算,但是我们发现,如果知道了父节点的所有信息,那么我们只需要比一下父节点的信息和自己,就知道自己能怎么跳

    问题就是如何快速求信息,因此想到从根节点往下求,用倍增算法。我们是设f[i][j]为i能够交易2的j次的点在哪,所以只要知道f[i][0]就可以通过倍增思想求出所有。

    现在的问题就是如果求f[i][0],因为我们从父节点往下求,因此现在知道所有父节点信息,所以拿父节点的信息和自己比大小,跳到小于等于自己的最远距离

    存在两种情况,一是父节点就比自己大,第二个就是在刚刚走到的位置再往上一格。

    所有跳出根或者到不了的都为0,因为初始为c,只要多一条c和出发点的边就行。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=3e5+10;
    int f[N][21];
    int to[N];
    int depth[N];
    int e[N],ne[N],h[N],idx;
    int a[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    int n,q;
    void dfs(int u,int fa){
        int i;
        int x=fa;
        for(i=20;i>=0;i--){
            if(f[x][i]&&a[f[x][i]]<=a[u])//一直跳直到不能跳
                x=f[x][i];
        }
        if(a[x]>a[u]) //判断是否u的父节点就大于u
            f[u][0]=x;
        else{
            f[u][0]=f[x][0];
        }
        depth[u]=depth[fa]+1;//根据深度判断是否已经跳过目标点
        for(i=1;i<=20;i++)
            f[u][i]=f[f[u][i-1]][i-1];
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa)
                continue;
            dfs(j,u);
        }
    }
    int main(){
        cin>>n>>q;
        memset(h,-1,sizeof h);
        int i;
        for(i=1;i<=n;i++) scanf("%d",&a[i]);
        for(i=1;i<n;i++){
            int x,b;
            scanf("%d%d",&x,&b);
            add(x,b);
            add(b,x);
        }
        for(i=n+1;i<=n+q;i++){
            int x,b,c;
            scanf("%d%d%d",&x,&b,&c);
            add(x,i);
            a[i]=c;
            to[i-n]=b;
        }
        dfs(1,0);
        ll ans=0;
        for(i=1;i<=q;i++){
            int v=to[i];
            ans=0;
            int u=i+n;
            for(int j=20;j>=0;j--){
                if(depth[f[u][j]]>=depth[to[i]]){ //根据深度判断,因为树已经重构,不知道v在哪
                    ans+=1<<j;
                    u=f[u][j];
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    osip状态机分析
    配置tomcat 加载指定的jar
    oracle创建用户并指定表空间
    CentOS7通过rsync+crontab实现两台服务器文件同步
    CentOS7配置MySQL5.7主备
    CentOS7本地安装MySQL5.7
    设置mysql 事务锁超时时间 innodb_lock_wait_timeout
    获取指定年月的第一天与最后一天
    Nginx 反向代理504 Gateway Time-out
    ubuntu下安装配置apache2与php
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12863185.html
Copyright © 2011-2022 走看看