• 美团 CodeM 复赛」城市网络


    美团 CodeM 复赛」城市网络

    内存限制:64 MiB时间限制:500 ms标准输入输出

    题目描述

    有一个树状的城市网络(即 nnn 个城市由 n−1n-1n1 条道路连接的连通图),首都为 111 号城市,每个城市售卖价值为 aia_iai​​ 的珠宝。

    你是一个珠宝商,现在安排有 qqq 次行程,每次行程为从 uuu 号城市前往 vvv 号城市(走最短路径),保证 vvv 在 uuu 前往首都的最短路径上。

    在每次行程开始时,你手上有价值为 ccc 的珠宝(每次行程可能不同),并且每经过一个城市时(包括 uuu 和 vvv),假如那个城市中售卖的珠宝比你现在手上的每一种珠宝都要优秀(价值更高,即严格大于),那么你就会选择购入。

    现在你想要对每一次行程,求出会进行多少次购买事件。

    输入格式

    第一行,两个正整数 n,qn , qn,q。

    第二行,nnn 个正整数 aia_iai​​ 描述每个城市售卖的珠宝的价值。

    接下来 n−1n-1n1 行,每行描述一条道路 x,yx , yx,y (1≤x,y≤n1 leq x , y leq n1x,yn),表示有一条连接 x 和 y 的道路。

    接下来 qqq 行,每行描述一次行程 u,v,cu , v , cu,v,c (1≤u,v≤n1 leq u , v leq n1u,vn)。

    输出格式

    对于每次行程输出一行,为所购买次数。

    样例

    样例输入

    5 4
    3 5 1 2 4
    1 2
    1 3
    2 4
    3 5
    4 2 1
    4 2 2
    4 2 3
    5 1 5

    样例输出

    2
    1
    1
    0

    数据范围与提示

    对于 100%100 \%100% 的数据,保证 2≤n≤105,1≤q≤1052 leq n leq 10^5 , 1 leq q leq 10^52n105​​,1q105​​ , 1≤ai≤1051 leq a_i leq 10^51ai​​105​​ , 1≤c≤1051 leq c leq 10^51c105​​。

    分析:有趣的技巧是把询问挂在起点下面当叶子;

       对于新树上的每个点找第一个比他大的祖先,可以倍增实现;

       对于一个点,第一个比他大的祖先得到之后又可以继续倍增;

       这样这个问题就完美解决了;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #define rep(i,m,n) for(i=m;i<=(int)n;i++)
    #define mod 1000000007
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    #define ls rt<<1
    #define rs rt<<1|1
    const int maxn=2e5+10;
    const int N=5e2+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,t,a[maxn],dep[maxn],to[maxn],fa[20][maxn];
    vi e[maxn];
    void dfs(int x,int y)
    {
        int pos=y;
        for(int i=19;i>=0;i--)if(fa[i][pos]&&a[fa[i][pos]]<=a[x])pos=fa[i][pos];
        if(a[pos]>a[x])fa[0][x]=pos;
        else fa[0][x]=fa[0][pos];
        for(int i=1;fa[i-1][fa[i-1][x]];i++)
        {
            fa[i][x]=fa[i-1][fa[i-1][x]];
        }
        dep[x]=dep[y]+1;
        for(int z:e[x])
        {
            if(z==y)continue;
            dfs(z,x);
        }
    }
    int main()
    {
        int i,j;
        int q;
        scanf("%d%d",&n,&q);
        rep(i,1,n)scanf("%d",&a[i]);
        rep(i,1,n-1)
        {
            scanf("%d%d",&j,&k);
            e[j].pb(k),e[k].pb(j);
        }
        rep(i,1,q)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            a[n+i]=z;
            e[n+i].pb(x);
            e[x].pb(n+i);
            to[n+i]=y;
        }
        dfs(1,0);
        rep(i,n+1,n+q)
        {
            int ret=0,pos=i;
            for(j=19;j>=0;j--)
            {
                if(dep[fa[j][pos]]>=dep[to[i]])
                {
                    ret+=(1<<j);
                    pos=fa[j][pos];
                }
            }
            printf("%d
    ",ret);
        }
        return 0;
    }
  • 相关阅读:
    CSP2021&NOIP2021游记
    P3835[模板]可持久化平衡树【无旋Treap】
    P4688[Ynoi2016]掉进兔子洞【莫队,bitset】
    C# (CSharp) ADODB.Command示例
    求最大公约数 算法记录
    流逝时间+Windows下监测文件夹
    C# WinForm开发系列 文章索引
    09年搞笑签名
    高三班主任写给学生的一封信(在读大学的要看完)
    北京生存法则
  • 原文地址:https://www.cnblogs.com/dyzll/p/7156090.html
Copyright © 2020-2023  润新知