zoukankan      html  css  js  c++  java
  • bzoj2870

    点分治

    跟路径有关的立马想到了点分治

    自然我们需要统计每条路径的答案,根据点分治的过程,考虑每条路径,我们希望当前路径上的点作为最小值

    那么我们用树状数组保存之前每个最小值对应的最长长度,跑两遍即可

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e4 + 5;
    vector<int> G[N];
    int n, root, m;
    long long ans;
    int t[N << 1], vis[N], v[N], mx[N], size[N];
    int getsize(int u, int last) {
        int ret = 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(vis[v] || v == last) {
                continue;
            }
            ret += getsize(v, u);
        }
        return ret;
    }
    void getroot(int u, int last, int S) {
        mx[u] = 0;
        size[u] = 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(v == last || vis[v]) {
                continue;
            }
            getroot(v, u, S);
            mx[u] = max(mx[u], size[v]);
            size[u] += size[v];
        }
        mx[u] = max(mx[u], S - size[u]);
        if(mx[u] < mx[root]) {
            root = u;
        }
    }
    void update(int x, int d) {
        for(; x; x -= x & -x) {
            if(d == -1) {
                t[x] = 0;
            } else {
                t[x] = max(t[x], d);
            }
        }
    }
    int query(int x) {
        int ret = 0;
        for(; x <= m; x += x & -x) {
            ret = max(ret, t[x]);
        }
        return ret;
    }
    void dp(int u, int last, int mn, int len) {
        mn = min(mn, v[u]);
        ans = max(ans, (long long)(len + query(mn + 1)) * mn);
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(vis[v] || v == last) {
                continue;
            }       
            dp(v, u, mn, len + 1);
        }
    }
    void dfs(int u, int last, int mn, int len, int mp) {
        mn = min(mn, v[u]);
        update(mn + 1, min(len + 1, mp));
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(vis[v] || v == last) {
                continue;
            }
            dfs(v, u, mn, len + 1, mp);
        }
    }
    void solve(int u) {
        vis[u] = 1;
        update(v[u] + 1, 1);
        for(int i = 0; i < G[u].size(); ++i) {
            int V = G[u][i];
            if(vis[V]) {
                continue;
            }
            dp(V, u, v[u], 1);
            dfs(V, u, v[u], 1, 1e9);
        }
        for(int i = 0; i < G[u].size(); ++i) {
            int V = G[u][i];
            if(vis[V]) {
                continue;
            }
            dfs(V, u, v[u], 1, -1);
        }
        update(v[u], 1);
        for(int i = G[u].size() - 1; i >= 0; --i) {
            int V = G[u][i];
            if(vis[V]) {
                continue;
            }
            dp(V, u, v[u], 1);
            dfs(V, u, v[u], 1, 1e9);
        }
        update(v[u], -1);
        for(int i = G[u].size() - 1; i >= 0; --i) {
            int V = G[u][i];
            if(vis[V]) {
                continue;
            }
            dfs(V, u, v[u], 1, -1);
        }
        for(int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            if(!vis[v]) {
                root = 0;
                getroot(v, u, getsize(v, u));
                solve(root);
            }
        }
    }
    int main() {
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &v[i]);
            m = max(m, v[i] + 1);
        }
        for(int i = 1; i < n; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        mx[0] = 1e9;
        getroot(1, 0, getsize(1, 0));
        solve(root);
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    网络通信
    jvm调优
    rokectMq
    mybatis属性类
    spring cloud feign
    spring cloud hystrix
    spring cloud ribbon
    mybatis(二)创建代理类执行sql
    内存操作函数
    堆空间的开辟与使用
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8467788.html
Copyright © 2011-2022 走看看