2019百度之星复赛的几道题

Quasi Binary Search Tree

贪心,重构二叉树,

1.如果左右子树最小节点都比当前节点大,则选择节点数少的子树当作左子树。节点数一样执行2

2.如果左子树最小节点比右子树最小节点大,则交换左右子树。

重构完成后中序遍历,标号

//
// Created by liulex on 2020/7/24.
//
#include <bits/stdc++.h>

using namespace std;
#define int long long
signed L[100005],R[100005];
bool vis[100005];
signed n;
signed lsz[100005],rsz[100005];
signed mi[100005],f[100005],A[100005];

signed dfs(signed x)
{
    mi[x] = 1e9;
    if(L[x]){
        mi[x] = min(mi[x],dfs(L[x]));
        f[x] = -1;
        lsz[x] = lsz[L[x]]+1;
    }
    if(R[x]){
        signed k = dfs(R[x]);

        if(k < mi[x]){
            f[x] = 1;
            mi[x] = k;
        }
        rsz[x] = rsz[R[x]] + 1;
    }
    return min(mi[x],x);
}
void build(signed x)
{
    if(mi[x] > x){
        if(lsz[x] > rsz[x]){
            swap(L[x],R[x]);
        }
    }else{
        if(f[x] == 1){
            swap(L[x],R[x]);
        }
    }
    if(L[x]){
    build(L[x]);}
    if(R[x]){
    build(R[x]);}
}
int cnt = 0;
void traver(int x){
    if(L[x]){
    traver(L[x]);
    }
    A[cnt++] = x;
    if(R[x]) {
        traver(R[x]);
    }
}
int mod = 1e9 + 7;
int F[100005];
void init()
{
    F[0] = 1;
    for(int i = 1; i <= 100000; i++){
        F[i] = (F[i-1]*233ll)%mod;
    }
}
signed main()
{
    signed T;
    init();
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            scanf("%d%d",&L[i],&R[i]);
            vis[L[i]] = true;
            vis[R[i]] = true;
        }
        signed root = -1;
        for(int i = 1; i <= n; i++){
            if(!vis[i]){
                root = i;
            }else{
                vis[i] = false;
            }
        }
        dfs(root);
        build(root);
        cnt = 1;
        traver(root);
        int ans = 0;
        for(int i = 1; i <= n; i++){
            ans = (ans +(i^A[i])*F[A[i]]%mod)%mod;
        }
        cout<< ans <<
        '
';
        for(int i = 1; i <= n; i++){
            lsz[i] = rsz[i] = mi[i] = f[i] = A[i] = 0;
        }

    }
}

Diversity

树形dp,dp[x][0]表示当前节点取L[x],dp[x][1]表示当前节点取R[x]

#include <bits/stdc++.h>
using namespace std;
vector<int> G[100005];
int L[100005],R[100005];
long long dp[100005][2];
int n,x,y;
void dfs(int x,int f)
{
    dp[x][0] = dp[x][1] = 0;
    for(auto i : G[x]){
        if(i != f){
            dfs(i,x);
            dp[x][0] += max(abs(L[x]-L[i])+dp[i][0],abs(L[x]-R[i])+dp[i][1]);
            dp[x][1] += max(abs(R[x]-L[i])+dp[i][0],abs(R[x]-R[i])+dp[i][1]);
        }
    }
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 0; i < n - 1; i++){
            scanf("%d%d",&x,&y);
            G[x].push_back(y);
        }
        for(int i = 1; i <= n; i++){
            scanf("%d%d",&L[i],&R[i]);
        }
        dfs(1,-1);
        cout<<max(dp[1][0],dp[1][1])<<'
';
        for(int i= 1;i <= n; i++){
            G[i].clear();
        }
    }
    return 0;
}

Transformation

打表找规律

//
// Created by liulex on 2020/7/24.
//
#include <bits/stdc++.h>
using namespace std;
#define int long long
int P[70];
void init()
{
    P[0] = 1;
    for(int i = 1; i <= 62; i ++) {
        P[i] = (P[i - 1] * 2ll);
    }
}
int a,b,c,d;
signed main()
{
    init();
    int T;
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
        if(a == b && (c != a ||d != b)){
            puts("No");
        }else if(a == c && b == d){
            puts("Yes");
            cout<<'
';
        }else if((c + d) &1){
            puts("No");
        }else if(a > b && (c < a || d > b)){
            puts("No");
        }else if(a < b && (d < b || c > a)){
            puts("No");
        }else{
            int r = abs(a - b);
            int k = abs(c - a);

            if(k%r != 0){
                puts("No");
            }else{

                k = k/r;
                string s = "";

                if(k == 0){

                }else if(k == 1){
                s = 'B';
                }else{
                int i = 0;
                while(k > P[i]){
                    k -= P[i];
                    i++;
                }
                s = 'B';
                while(i > 0) {
                    if (k <= P[i] / 2) {
                         s = 'A'+s;
                    }else {
                        k -= P[i]/2;
                        s = 'B' + s;
                    }
                    i--;
                }


                }

                bool flag = (a > b);

                for(auto& i: s){
                    if(i == 'A'){
                        b = 2*b - a;
                    }else{
                        a = 2*a - b;
                    }
                }
                if(flag && b < d){
                    puts("No");
                }else if((!flag) && b > d){
                    puts("No");
                }else{

                    int u = b-a;
                    int o = b;
                    for(int i=0;i<62;i++){

                        if(((u > 0) && (P[i] - 1) * u + o > d)||(u < 0 &&(P[i] - 1) * u + o < d)){
                            puts("No");
                            break;
                        }else if((P[i] - 1) * u + o == d){

                            for(int j = 0; j < i ; j ++){
                                s += 'A';
                            }
                            puts("Yes");
                            cout<<s<<'
';
                            break;
                        }
                    }
                }


            }
        }
    }
}
原文地址:https://www.cnblogs.com/liulex/p/13375849.html