P5836 [USACO19DEC] Milk Visits S (connected blocks on the tree || prefix and + LCA on the tree)

Title Portal

Topic: Give a tree of n nodes, each point has two colors, m times inquiries, whether there are nodes of a certain color on the path of the two points, there is output 1, there is no output 0.

And check the idea: we connect the nodes of the same state connected to a tree, then for the query, if the two points of the query are in the same connected block, and the color of the query is not the color of the connected block, then No, the rest is true. When traversing dfs, pay attention to pruning, otherwise a sai for the whole picture will be cold.

LCA idea: because there is only one color for each point, then we use two arrays to store the point to the root of the tree. How many are there for the two colors, then we find the two points given and ask for LCA, then You will find that the color on the path of these two points can be obtained, it is recommended to draw a deeper impression by yourself.

And check the code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int eps=1e-6;
typedef long long ll;
typedef unsigned long long ull;
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
#define null NULL
int fa[N];
int finds(int x)
{
    return fa[x]==x?x:fa[x]=finds(fa[x]);
}
int head[N],nxt[N],to[N],tot=0;
void add(int u,int v)
{
    nxt[++tot]=head[u];
    to[tot]=v;
    head[u]=tot;
}
string s;
void dfs(int x,int y)
{
    if(s[x-1]!=s[y-1])
        return ;
    if(finds(x)==finds(y)&&x!=y)
        return ;
    fa[finds(x)]=finds(y);
    for(int i=head[x];i;i=nxt[i])
    {
        if(to[i]!=y)
        {
            dfs(to[i],x);
        }
    }
}
signed main()
{
    IOS;
    int n,m;
    cin>>n>>m;
    cin>>s;
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)
    {
        dfs(i,i);
    }
    while(m--)
    {
        int a,b;char c;
        cin>>a>>b>>c;
        if(fa[a]==fa[b]&&s[a-1]!=c)
        {
            cout<<0;
        }
        else
            cout<<1;
    }
}

LCA code

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int inf=0x7fffffff;
const int mod=1e9+7;
const int eps=1e-6;
typedef long long ll;
typedef unsigned long long ull;
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl '\n'
#define null NULL
int head[N],nxt[N],to[N],tot=0;
void add(int u,int v)
{
    nxt[++tot]=head[u];
    to[tot]=v;
    head[u]=tot;
}
string s;
int deep[N],fa[N][30];int h[N],g[N];int lg[N];
void dfs(int x,int y)
{
    deep[x]=deep[y]+1;fa[x][0]=y;
    if(s[x-1]=='H')
    {
        h[x]=h[y]+1;
        g[x]=g[y];
    }
    else
    {
        g[x]=g[y]+1;
        h[x]=h[y];
    }
    for(int i=1;i<=lg[deep[x]];i++)
    {
        fa[x][i]=fa[fa[x][i-1]][i-1];
    }
    for(int i=head[x];i;i=nxt[i])
    {
        if(to[i]!=y)
        {
            dfs(to[i],x);
        }
    }
}
int lca(int x,int y)
{
    if(deep[x]<deep[y])
        swap(x,y);
    while(deep[x]>deep[y])
    {
        x=fa[x][lg[deep[x]-deep[y]]];
    }
    if(x==y)
        return x;
    for(int i=lg[deep[x]];i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            x=fa[x][i];y=fa[y][i];
        }
    }
    return fa[x][0];
}
signed main()
{
    IOS;
    int n,m;
    cin>>n>>m;
    cin>>s;
    for(int i=1;i<=n-1;i++)
    {
        int u,v;
        cin>>u>>v;
        add(u,v);add(v,u);
    }
    for(int i=2;i<=n;i++)
        lg[i]=lg[i>>1]+1;
    dfs(1,0);
    while(m--)
    {
        int a,b;char c;
        cin>>a>>b>>c;
        int l=lca(a,b);
        int hh=h[a]+h[b]-2*h[fa[l][0]],gg=g[a]+g[b]-2*g[fa[l][0]];
        if(s[l-1]=='H')
            hh--;
        else
            gg--;
        if((c=='H'&&hh>0)||(c=='G'&&gg>0))
            cout<<1;
        else
            cout<<0;
    }
}

Published 93 original articles · won praise 9 · views 4203

Guess you like

Origin blog.csdn.net/Joker_He/article/details/105335917