libreoj 6192 "American League CodeM Rematch" city network solution

Blog viewing effect is better

Brief description of the title

There are \ (n \) cities forming a tree network. Jewels with a value of \ (a_i \) are sold in the \ (i \) th city . The parents of zps planned \ (q \) trips. Every first bring value to \ (c \) of jewelry, from the city \ (u \) went to the city \ (v \) (guarantee \ (v \) in \ (u \) to \ (1 \) of On the path). If the jewelry sold in the current city is more expensive than the one at hand (strictly greater than, equal to not), then zps' parents will buy the jewelry.

For each trip, find out how many "buy" operations the parents of zps have performed.

\ (n, q, c, a_i \ le 10 ^ 5 \)\ (1 \ le u, v \ le n \)

Ideas

We found that for each trip, except for the first special judgment, where I should go next time should be fixed.

Suppose we are currently in \ (u \) , then the next time we go, it should be that \ (u \) jumps up, the first \ (a_i> a_u \) 's \ (i \) (of course, if this \ (i \) jumped out of \ (v \) , then we do n’t count it)

So we consider, first multiplier obtains the first \ (a_i> a_u \) a \ (I \) , and then re-built FIG, the \ (U \) directly connected to the \ (I \) on. In this way, for each trip, after we distinguish the first and the last special, it is equivalent to finding the length of a path on the new tree. This can be obtained by directly maintaining a depth.

Code

#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define N 155555
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)
    #define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
    #define p_b push_back
    #define sz(a) ((int)a.size())
    #define iter(a,p) (a.begin()+p)
    int I()
    {
        int x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return (x=(f==1)?x:-x);
    }
    void Rd(int cnt,...)
    {
        va_list args; va_start(args,cnt);
        F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();}
        va_end(args);
    }
    class Graph
    {
        public:
            int head[N];
            int EdgeCount;
            struct Edge
            {
                int To,Label,Next;
            }Ed[N<<1];
            void clear(int _V=N,int _E=N<<1) 
            {
                memset(Ed,-1,sizeof(Edge)*(_E));
                memset(head,-1,sizeof(int)*(_V));
                EdgeCount=-1;
            }
            void AddEdge(int u,int v,int w=1)
            {
                Ed[++EdgeCount]=(Edge){v,w,head[u]};
                head[u]=EdgeCount;
            }
            void Add2(int u,int v,int w=1) {AddEdge(u,v,w);AddEdge(v,u,w);}
            int Start(int u) {return head[u];}
            int To(int u){return Ed[u].To;}
            int Label(int u){return Ed[u].Label;}
            int Next(int u){return Ed[u].Next;}
    }G;
    
    int n,m;
    int a[N];
    void Input()
    {
        Rd(2,&n,&m);
        F(i,1,n) a[i]=I();
        G.clear();
        F(i,1,n-1)
        {
            int u,v; Rd(2,&u,&v); G.Add2(u,v);
        }
    }

    int deep[N],fa[N][22],Max[N][22];
    void DFS(int u,int f)
    {
        deep[u]=(u==f)?0:deep[f]+1;
        fa[u][0]=f; F(i,1,20) fa[u][i]=fa[fa[u][i-1]][i-1];
        Max[u][0]=max(a[u],a[f]); F(i,1,20) Max[u][i]=max(Max[u][i-1],Max[fa[u][i-1]][i-1]);
        Tra(i,u) if (v!=f) DFS(v,u);
    }
    int PathMax(int u,int f) // 求路径最大值
    {
        if (u==f) return a[u];
        int ans=0;
        D(i,20,0) if (deep[fa[u][i]]>=deep[f]) 
        {
            ans=max(ans,Max[u][i]),u=fa[u][i];
        }
        
        return ans;
    }
    int MaxPos(int u,int f) // 求路径最大值是哪个位置
    {
        int Mx=PathMax(u,f);
        if (a[u]==Mx) return u;
        D(i,20,0) if (Max[u][i]<Mx) u=fa[u][i]; 
        return fa[u][0];
    }
    int FirstBig(int u,int c) // 找到 u 往上第一个满足 a[i]>c 的
    {
        if (a[u]>c) return u;
        if (Max[u][20]<=c) return n+1;
        D(i,20,0) if (Max[u][i]<=c) u=fa[u][i];
        return fa[u][0];
    }
    namespace Re_build // 把重新建的图封装起来,避免名字冲突
    {   
        Graph G;
        int deep[N],fa[N][22];
        void Init()
        {
            G.clear();
            F(i,1,n) G.AddEdge(fa[i][0],i); 
        }
        void DFS(int u)
        {
            deep[u]=(u==n+1)?0:deep[fa[u][0]]+1;
            F(i,1,20) fa[u][i]=fa[fa[u][i-1]][i-1];
            Tra(i,u) DFS(v);
        }
        int  Query(int u,int fu) {return deep[u]-deep[fu];}
    }
    void Soviet()
    {
        DFS(1,1);
        F(i,1,n) Re_build::fa[i][0]=(Max[i][20]==a[i])?n+1:FirstBig(i,a[i]);
        // 重新设置 fa 数组
        Re_build::Init();
        Re_build::DFS(n+1);
        // 重新 DFS 一遍

        F(i,1,m)
        {
            int u,v,c; Rd(3,&u,&v,&c); 
            int uu=u,vv=v; // 存储原始的 u,v (后面会有修改)
            if (u==v) {puts(c<a[u]?"1":"0"); continue;}
            if (c>=PathMax(u,v)) {puts("0"); continue;}
            u=FirstBig(uu,c);  // 先跳到上面第一个 >c 的 (注意,这里先跳了一次,所以答案+1)
            v=MaxPos(uu,vv); // 处理一下开头结尾
            printf("%d\n",Re_build::Query(u,v)+1); 
            // 如上面所说,答案 +1
        }
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}

Guess you like

Origin www.cnblogs.com/LightningUZ/p/12729652.html