G

对抗搜索也叫极大极小值搜索,其核心思想就是先搜到底部,将叶子节点的值返回上去,之后极大节点选择所有分支里的极大值返回,极小节点选择所有分支里的极小值返回。

对顶堆维护中位数。emmm其实对顶堆维护中位数是一个板子,不过注意这里会有奇偶中位数。

注意一下就行了

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f; ///1061109567
const int maxn = 1e5+10;


int n, m;
int dp[maxn];
int a[maxn];
vector<int> G[maxn];

namespace DDD {
    multiset<int, less<int> > big;
    multiset<int, greater<int> > small;
    //int k;
    int cnt; ///只求中位数
    void init(int kk=1) {
        small.clear();
        big.clear();
        //k = kk;
        cnt = 0;
    }
    void balance() {
        ///维持上方小根堆比下面大根堆 多k (奇偶会不为k)
        while (big.size() > small.size() + (cnt%2==0)) {
            small.insert(*big.begin());
            big.erase(big.begin());
        }
        while (small.size() + (cnt%2==0) > big.size()) {
            big.insert(*small.begin());
            small.erase(small.begin());
        }
    }
    void _insert(int x) {
        if (big.size() == 0 || x >= *big.begin()) {
            big.insert(x);
        }
        else {
            small.insert(x);
        }
        balance();
        cnt ++;
    }
    int get() {
//        cout << "in small: ";
//        for (auto i : small ) {
//            cout << i << " ";
//        }
//        cout << endl;
//        cout << "in big: ";
//        for (auto i : big) {
//            cout << i << " ";
//        }
//        cout << endl;
        if (cnt % 2) return *big.begin();
        return (*small.begin() + *big.begin()) / 2;
    }

    void _delete(int x) {
        auto p1 = small.find(x);
        auto p2 = big.find(x);
        if (p1 != small.end()) {
            small.erase(p1);
            balance();
            cnt --;
        }
        else if (p2 != big.end()) {
            big.erase(p2);
            balance();
            cnt --;
        }

    }
};

void DFS(int u, int fa, int d) {
//    cout << "node: " << u << endl;
    DDD::_insert(a[u]);
    int mx = 0, mi = 1e9;
    for (auto v : G[u]) {
        if (v == fa) continue;
        DFS(v, u, d+1);
        mi = min(dp[v], mi);
        mx = max(dp[v], mx);
    }
    if (mx == 0) {
        dp[u] = DDD::get();
//        cout << u << " " << dp[u] << endl;
    }
    else if (d&1) dp[u] = mi;
    else dp[u] = mx;
    DDD::_delete(a[u]);
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n-1; ++ i) {
        int u, v;scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    DDD::init();
    DFS(1, 0, 0);
    cout << dp[1] << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/Vikyanite/p/15263093.html