Astar 2019 Quasi Binary Search Tree

The meaning of problems

To a \ (n-\) binary points, each point is marked with \ (1 \) to \ (\ n-) in different numbers

A tree is defined as a pseudo-binary tree if and only if, for each node, its left subtree labels of all nodes is less than its own, right child nodes are greater than all the reference itself; numeral or all the nodes in the left subtree greater than its own, reference numeral right subtree of all nodes is less than its own

Now there is an unlabeled tree, give it a label makes it a pseudo-binary tree. If multiple sets of solutions, output a lexicographically smallest solution, i.e., comparative \ (1 \) number of the reference point, and then compare \ (2 \) number of reference points, and so on


solution

The tree was first consider a standard binary search tree in the form of how we label them:

The problem is that we can find a standard partition solving form

Specifically, it is traversed from the root node, and fill its left subtree size plus a number at the root node

Then you can deal with, respectively, two sub-tree, apparently they are independently of each other's;

But this question is not a given number of standard binary search tree , but a pseudo-binary tree

So traverse to the current node can either fill the left subtree size plus a number, you can also fill in the right subtree size plus a number

If the number of violence fill complexity is \ (O (2 ^ N) \) th power, unacceptable

At this point we can find another topic of restrictions: the lexicographically smallest

This condition can be used as the basis of our choice in the number of refills

When transferring to discuss classified, annotated code


Code

#include <cstdio>
#include <cstring>

using namespace std;

const int N = 1e5 + 10;
const int mod = 1e9 + 7;

int n, t, rt;
int ls[N], rs[N], mn[N], sz[N], deg[N];

int res[N];

inline int min(int x, int y) {
    return x < y ? x : y;   
}

inline int qpow(int x, int y) {
    int ret = 1;
    while (y) {
        if (y & 1)  ret = 1LL * ret * x % mod;
        x = 1LL * x * x % mod, y >>= 1;
    }
    return ret;
}

void dfs(int x) {   //预处理出子树大小与子树最小值 
    sz[x] = 1, mn[x] = x;
    if (ls[x])  
        dfs(ls[x]), sz[x] += sz[ls[x]], mn[x] = min(mn[x], mn[ls[x]]);
    if (rs[x])
        dfs(rs[x]), sz[x] += sz[rs[x]], mn[x] = min(mn[x], mn[rs[x]]);
}

void DFS(int x, int l, int r) {
    if (l == r) return res[x] = l, void();
    if (ls[x] && rs[x]) {               //若既有左儿子也有右儿子 
        int lc = sz[ls[x]], rc = sz[rs[x]]; 
        if (mn[x] == x) {               //若当前节点就是其所在子树中最小值,贪心选取使它最小 
            if (lc < rc) {
                DFS(ls[x], l, l + lc - 1);
                DFS(rs[x], l + lc + 1, r);
                res[x] = l + lc;
            } else if (lc > rc) {
                DFS(ls[x], l + rc + 1, r);
                DFS(rs[x], l, l + rc - 1);
                res[x] = l + rc;
            } else {                    //这里讨论的情况不能与下面的合并
                if (mn[ls[x]] < mn[rs[x]]) {
                    DFS(ls[x], l, l + sz[ls[x]] - 1);
                    DFS(rs[x], r - sz[rs[x]] + 1, r);
                    res[x] = l + sz[ls[x]];
                } else {
                    DFS(rs[x], l, l + sz[rs[x]] - 1);
                    DFS(ls[x], l + sz[rs[x]] + 1, r);
                    res[x] = l + sz[rs[x]];               
                }                   
            }
        } else {
            if (mn[x] == mn[ls[x]]) {   //如果最小值在左子树,即选择让左子树更优 
                DFS(ls[x], l, l + lc - 1);
                DFS(rs[x], l + lc + 1, r);
                res[x] = l + lc;    
            }
            if (mn[x] == mn[rs[x]]) {   //否则选择让右子树最优 
                DFS(ls[x], l + rc + 1, r);
                DFS(rs[x], l, l + rc - 1);
                res[x] = l + rc;
            }
        }
    } else {    //如果仅有左/右儿子,讨论一下当前节点是否为最小值即可 
        if (ls[x]) {     
            if (mn[x] == x)
                res[x] = l, DFS(ls[x], l + 1, r);
            else
                res[x] = r, DFS(ls[x], l, r - 1);
        }
        if (rs[x]) {
            if (mn[x] == x)
                res[x] = l, DFS(rs[x], l + 1, r);
            else 
                res[x] = r, DFS(rs[x], l, r - 1);
        }
    }
        
}

long long solve() {
    long long ret = 0;
    for (int i = 1; i <= n; ++i)
        ret = (ret + 1LL * (res[i] ^ i) * qpow(233, i) % mod) % mod;    
    return ret;
}

int main() {
    
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);    
        for (int i = 1; i <= n; ++i)    
            deg[i] = 0;     
        for (int i = 1; i <= n; ++i)
            scanf("%d%d", ls + i, rs + i);
        for (int i = 1; i <= n; ++i)
            deg[ls[i]]++, deg[rs[i]]++;
        rt = 1;
        while (deg[rt]) ++rt;
        
        dfs(rt);
        DFS(rt, 1, n);
        
        printf("%lld\n", solve());
    }
    
}

Guess you like

Origin www.cnblogs.com/VeniVidiVici/p/11443353.html