2019百度之星 - 复赛 HDU-6727 Quasi Binary Search Tree 构造 二叉树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6727

题解:对于当前节点,肯定分为两个区间一个在左一个在右,就把小区间分到最小编号在的那个分支中,如果当前节点最小,那就尽可能让当前节点的标号小,思路很简单,可能我写麻烦了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const ll mod = 1e9 + 7;
int nex[N][2];
int id[N];
int in[N];
int num[N][2];
int minn[N][2];
void dfs(int u) {
    int to;
    num[u][0] = num[u][1] = 0;
    minn[u][0] = minn[u][1] = N;
    if(nex[u][0]) {
        to = nex[u][0];
        dfs(to);
        num[u][0] = num[to][0] + num[to][1] + 1;
        minn[u][0] = min(minn[to][0], minn[to][1]);
        minn[u][0] = min(minn[u][0], to);
    }
    if(nex[u][1]) {
        to = nex[u][1];
        dfs(to);
        num[u][1] = num[to][0] + num[to][1] + 1;
        minn[u][1] = min(minn[to][0], minn[to][1]);
        minn[u][1] = min(minn[u][1], to);
    }
//    cout << u << " " << num[u][0] << " " << num[u][1] << endl;
}
int n;

void dfs1(int u, int l, int r) {
//    cout << u << " " << l <<  " " <<r << endl;
    int num1 = num[u][0];
    int num2 = num[u][1];
    if(num1 == 0 && num2 == 0) {
        id[u] = l;
    }else if(num1 == 0) {
        if(minn[u][1] > u) {
            id[u] = l;
            if(nex[u][1]) dfs1(nex[u][1], l + 1, r); 
        } else {
            id[u] = r;
            if(nex[u][1]) dfs1(nex[u][1], l, r - 1);
        }
    } else if(num2 == 0) {
        if(minn[u][0] > u) {
            id[u] = l;
            if(nex[u][0]) dfs1(nex[u][0], l + 1, r); 
        } else {
            id[u] = r;
            if(nex[u][0]) dfs1(nex[u][0], l, r - 1);
        }
    }
    else {
        if(u < minn[u][0] && u < minn[u][1]) {
            if(num1 < num2 || (num1 == num2 && minn[u][0] < minn[u][1])) {
                id[u] = l + num1;
                if(nex[u][0]) dfs1(nex[u][0], l, l + num1 - 1);
                if(nex[u][1]) dfs1(nex[u][1], l + num1 + 1, r);
            } else {
                id[u] = l + num2;
                if(nex[u][0]) dfs1(nex[u][0], l + num2 + 1, r);
                if(nex[u][1]) dfs1(nex[u][1], l, l + num2 - 1);
            }
        
            
        } else {
            if(minn[u][0] < minn[u][1]) {
                id[u] = l + num1;
                if(nex[u][0]) dfs1(nex[u][0], l, l + num1 - 1);
                if(nex[u][1]) dfs1(nex[u][1], l + num1 + 1, r);
            } else {
                id[u] = l + num2;
                if(nex[u][0]) dfs1(nex[u][0], l + num2 + 1, r);
                if(nex[u][1]) dfs1(nex[u][1], l, l + num2 - 1);
            }
        }
    
    }
    
}
ll f[N];
int main() {
    f[1] = 233;
    for(int i = 2; i < N; i++)
        f[i] = f[i - 1] * 233 % mod;
    int T;
    int x, y;
    int rt;
    scanf("%d", &T);
    ll ans;
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i <= n; i++) {
            nex[i][0] = nex[i][1] = 0;
            in[i] = 0;
        }
        for(int i = 1; i <= n; i++) {
            scanf("%d %d", &x, &y);
            nex[i][0] = x;
            nex[i][1] = y;
            in[x]++; in[y]++;
        }
        for(int i = 1; i <= n; i++)
            if(!in[i]) {
                rt = i;
                break;
            }
        dfs(rt);
        dfs1(rt, 1, n);
        ans = 0;
        for(int i = 1; i <= n; i++) {
        //    cout << id[i] << endl;
            ans = (ans + (id[i] ^ i) * f[i] % mod) % mod;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
/*
5
0 0
0 0
0 4
2 1
0 3

4
2 4
3 0
0 0
0 0

4
4 0
1 0
2 0
0 0

4
2 3
0 0
0 0
1 0

*/


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值