现在的位置: 首页 > 综合 > 正文

HDU 4409 Family Name List 简单树操作

2018年04月25日 ⁄ 综合 ⁄ 共 2245字 ⁄ 字号 评论关闭

题意:按照题目描述给一棵树(家族谱,节点n<=30000),有m(m<=30000)次操作,L代表字典序最小的dfs序列,b name 输出name的brother有多少个,

          c name name输出两个人的lca是多少(lca不能是name本身)。

题解:vector存储节点数这样很容易排序,然后保存下L的序列,sum[ i ]表示当前 i 节点的直接儿子节点的个数,rmq处理出lca。


Sure原创,转载请注明出处。

#pragma comment (linker , "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string.h>
#include <map>
#include <string>
#include <cmath>
using namespace std;
const int maxn = 30002;
vector <int> vv[maxn];
map <string , int> hash;
string name[maxn],str;
int up[maxn],dep[maxn],biao[maxn],sum[maxn],fa[maxn];
int E[maxn << 1],D[maxn << 1],bj[maxn],dp[maxn << 1][17];
int m,n,top,tot,bound;

bool cmp(int a,int b)
{
    return name[a] < name[b];
}

void init()
{
    memset(up,-1,sizeof(up));
    memset(sum,0,sizeof(sum));
    memset(fa,-1,sizeof(fa));
    hash.clear();
    for(int i=0;i<n;i++)
    {
        vv[i].clear();
    }
    return;
}

void read()
{
    getchar();
    cin>>name[0];
    up[0] = 0;
    for(int i=1;i<n;i++)
    {
        cin>>str;
        int j = 0,len = str.length();
        while(str[j] == '.') j++;
        up[j] = i;
        vv[up[j-1]].push_back(i);
        name[i] = str.substr(j);
        hash[name[i]] = i;
    }
    return;
}

void dfs(int st,int h)
{
    dep[st] = h;
    biao[tot++] = st;
    E[++top] = st;
    D[top] = h;
    bj[st] = top;
    for(int i=0;i<vv[st].size();i++)
    {
        fa[vv[st][i]] = st;
        sum[st]++;
        dfs(vv[st][i] , h+1);
        E[++top] = st;
        D[top] = h;
    }
    return;
}

void init_rmq()
{
    for(int i=1;i<=top;i++)
    {
        dp[i][0] = i;
    }
    for(int j=1;j<=bound;j++)
    {
        for(int i=1;i + (1 << j) - 1 <= top;i++)
        {
            if(D[dp[i][j-1]] < D[dp[i + (1 << (j-1))][j-1]])
            {
                dp[i][j] = dp[i][j-1];
            }
            else
            {
                dp[i][j] = dp[i + (1 << (j-1))][j-1];
            }
        }
    }
    return;
}

int askrmq(int l,int r)
{
    if(l > r) swap(l , r);
    int d = log((double)(r - l + 1)) / log(2.0);
    int wei = -1;
    if(D[dp[l][d]] < D[dp[r - (1 << d) + 1][d]])
    {
        wei = dp[l][d];
    }
    else
    {
        wei = dp[r - (1 << d) + 1][d];
    }
    return E[wei];
}

void make()
{
    for(int i=0;i<n;i++)
    {
        sort(vv[i].begin() , vv[i].end() , cmp);
    }
    top = tot = 0;
    dfs(0,0);
    bound = log((double)(top + 1)) / log(2.0);
    init_rmq();
    return;
}

void out()
{
    for(int i=0;i<tot;i++)
    {
        for(int j=0;j<dep[biao[i]];j++) printf(".");

        cout<<name[biao[i]]<<endl;
    }
    return;
}

void solve()
{
    scanf("%d",&m);
    getchar();
    char cc[3];
    while(m--)
    {
        scanf("%s",cc);
        if(cc[0] == 'L') out();
        else if(cc[0] == 'b')
        {
            cin>>str;
            int pos = hash[str];
            if(pos == 0) puts("1");
            else printf("%d\n",sum[fa[pos]]);
        }
        else
        {
            cin>>str;
            int x = hash[str];
            cin>>str;
            int y = hash[str];
            int lca = askrmq(bj[x] , bj[y]);
            if(lca == x) lca = fa[lca];
            if(lca == y) lca = fa[lca];
            cout<<name[lca]<<endl;
        }
    }
    return;
}

int main()
{
    while(scanf("%d",&n) && n)
    {
        init();
        read();
        make();
        solve();
    }
    return 0;
}

抱歉!评论已关闭.