羅区P3398 LCAの裁判官の交差点

トピックリンク:ポイントI

質問の意味:

無根木では、二本の鎖が交差するか否かが判断されます。
範囲:ポイント問い合わせ1E5 1E5ビュー
ツリーノードの数および照会の数を示す第1行2つの正の整数nおよびqは、の。
次に、2つの正の整数、UおよびV、uがノードvの間にエッジが存在する表現するノードのN-1行。
次のQ 4つの正の整数の列、B、C、およびD、ノード番号を表し、およびAB CDチェーンストランドの交点かどうかを尋ねます。
例:
5. 5
2 5
4 2
。1. 3
。1. 4
。5 1 5 1
2 1 2 4
。4. 3. 1. 4
。3. 1. 5 1
。3. 5. 1. 4
出力:
各質問について、共通点がある場合、大文字の出力が"Y" ;そうでなければ出力「N」。
Y
N
Y
Y
Y

ソリューション:

前記一方の鎖、他方の鎖上の2つのエンドポイントの共通の祖先:チェーン交差点2種があり、次の規則がなければなりません。

コード:

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define maxn 500005
#define IOS ios::sync_with_stdio(false)

struct edge
{
    int next, to;
};

edge ff[2 * maxn];
int head[2 * maxn], num;
void add(int from, int to)
{
    ff[++num].next = head[from];
    ff[num].to = to;
    head[from] = num;
}

int Eu[2 * maxn], id;	//记录欧拉序列
int dd[maxn];			//每一点的深度
int hId[maxn];		//记录每一点对应欧拉序列第一次出现的位置(映射)
bool vis[maxn];
int dis[maxn];//记录到根节点的距离
void dfs(int fa,int x, int d)
{
    dis[x]=dis[fa]+1;
    dd[x] = d;
    Eu[++id] = x;
    hId[x] = id;
    vis[x] = true;
    for (int i = head[x]; i != -1; i = ff[i].next)
    {
        if (vis[ff[i].to] == false)
        {
            dfs(x,ff[i].to, d + 1);
            Eu[++id] = x;
        }
    }
}

int f[2 * maxn][32];
int res[2 * maxn][32];

void ST_Init(int n)
{
    for (int i = 1; i <= n; i++)
    {
        f[i][0] = dd[Eu[i]];
        res[i][0] = Eu[i];
    }
    int depth = (int)(log2(n));
    for (int j = 1; j <= depth; j++)
        for (int i = 1; i <= n - (1 << j) + 1; i++)
        {
            if (f[i][j - 1]<f[i + (1 << (j - 1))][j - 1])
            {
                f[i][j] = f[i][j - 1];
                res[i][j] = res[i][j - 1];
            }
            else
            {
                f[i][j] = f[i + (1 << (j - 1))][j - 1];
                res[i][j] = res[i + (1 << (j - 1))][j - 1];
            }
        }
}

int ST_Query(int l, int r)
{
    int p = (int)(log2(r - l + 1));
    if (f[l][p]<f[r - (1 << p) + 1][p])
        return res[l][p];
    else
        return res[r - (1 << p) + 1][p];
}

int get_lca(int x,int y)
{
    int l,r;
    if (hId[x]<hId[y])
        l = hId[x], r = hId[y];
    else
        l = hId[y], r = hId[x];
    return ST_Query(l, r);
}

void init()
{
    memset(head, -1, sizeof(head));
    memset(vis, 0, sizeof(vis));
    num = 0;
}

int main()
{
    IOS;
    int n, m, k;
    cin>>n>>m;
    k=1;
    init();
    for (int i = 0; i<n - 1; i++)
    {
        int x, y;
        cin>>x>>y;
        add(x, y), add(y, x);
    }

    dfs(k,k, 1);
    ST_Init(id);

    for (int i = 0; i<m; i++)
    {
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        int lca1=get_lca(x1,y1);
        int lca2=get_lca(x2,y2);
        int d1=dis[x1]+dis[y1]-2*dis[lca1]; //the distance of x1->y1
        int d2=dis[x2]+dis[y2]-2*dis[lca2]; // the distance of x2->y2
        bool flag=false;
        //判断lca1是否在x2->y2中
        int d3=dis[x2]+dis[lca1]-2*dis[get_lca(x2,lca1)];//the distance of x2->lca1
        int d4=dis[y2]+dis[lca1]-2*dis[get_lca(y2,lca1)];//the distance of y2->lca1
        if(d3+d4==d2) //lca1在x2->y2中
        {
            flag=true;
        }
        else
        {
            //判断lca2是否在x1->y1中
            int d5=dis[x1]+dis[lca2]-2*dis[get_lca(x1,lca2)];//the distance of x1->lca2
            int d4=dis[y1]+dis[lca2]-2*dis[get_lca(y1,lca2)];//the distance of y1->lca2
            if(d5+d4==d1)//lca2在x1->y1中
            {
                flag=true;
            }
        }
        if(flag)
            cout<<"Y\n";
        else
            cout<<"N\n";
    }
    return 0;
}

公開された41元の記事 ウォンの賞賛2 ビュー1216

おすすめ

転載: blog.csdn.net/qq_41418281/article/details/104065961