zoukankan      html  css  js  c++  java
  • HDU 6162

    /*
    HDU 6162 - Ch’s gift [ LCA,线段树 ]  |  2017 ZJUT Multi-University Training 9
    题意:
    	N节点的树,Q组询问
    	每次询问s,t两节点之间的路径上点权值在[a,b]之间的点权总和
    分析:
    	求出每个询问的LCA,然后离线
    	按dfs顺序更新树状数组,即某点处树状数组中存的值为其所有祖先节点的值
    	每个点处对答案的贡献为:
    		当其为第 i 个 lca 时, ans[i] -= 2 * query(a,b) , 再特判该节点
    		当其为第 i 个 s,t 时, ans[i] += query(a,b)
    */
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    const int N = 1e5+5;
    typedef pair<int, int> P;
    vector<int> G[N];//存边
    vector<P> QQ[N];
    int a[N], b[N*4], cnt, n, Q;
    struct Query {
        int s, t, lca, a, b;
    }q[N];
    void addedge(int u, int v) {
        G[u].push_back(v);
    }
    namespace LCA {
        struct Query {
            int v, q;
        }; vector <Query> query[N];//存每个点的询问
        int ans[N], f[N], vis[N];
        int sf(int x) {
            return x == f[x] ? x : f[x] = sf(f[x]);
        }
        void init() {
            memset(ans, -1, sizeof(ans));
            for (int i = 0; i < N; i++) {
                vis[i] = 0; f[i] = i; query[i].clear();
            }
        }
        void adq(int u, int v, int id) {//添加询问
            query[u].push_back(Query{v, id});
            query[v].push_back(Query{u, id});
        }
        void LCA(int u) {
            f[u] = u, vis[u] = 1;
            for (auto& x : query[u]) {
                if (vis[x.v] && ans[x.q] == -1)
                    ans[x.q] = sf(x.v);
            }
            for (auto& v : G[u]) {
                if (vis[v]) continue;
                LCA(v);
                f[v] = u;
            }
        }
    }
    void init2()
    {
        cnt = 0;
        for (int i = 1; i <= n; i++) b[++cnt] = a[i];
        for (int i = 1; i <= Q; i++)
        {
            b[++cnt] = q[i].a;
            b[++cnt] = q[i].b;
        }
        sort(b+1, b+cnt+1);
        cnt = unique(b+1, b+cnt+1) - (b+1);
        for (int i = 1; i <= n; i++)
            a[i] = lower_bound(b+1, b+cnt+1, a[i]) - b;
        for (int i = 1; i <= Q; i++)
        {
            q[i].a = lower_bound(b+1, b+cnt+1, q[i].a) - b;
            q[i].b = lower_bound(b+1, b+cnt+1, q[i].b) - b;
        }
    }
    LL ans[N], c[N<<4];
    void modify(int x, LL num){
        while (x <= cnt) c[x] += num, x += x&-x;
    }
    LL sum(int x) {
        LL s = 0;
        while (x) s += c[x], x -= x&-x;
        return s;
    }
    void init()
    {
        memset(c, 0, sizeof(c));
        for (int i = 0; i < N; i++) G[i].clear();
        for (int i = 0; i < N; i++) QQ[i].clear();
        memset(ans, 0, sizeof(ans));
    }
    void dfs(int u, int pre)
    {
        modify(a[u], b[a[u]]);
        LL tmp;
        for (auto & qq : QQ[u])
        {
            tmp = sum(q[qq.first].b) - sum(q[qq.first].a-1);
            if (qq.second == -1)
            {
                ans[qq.first] -= 2*tmp;
                if (a[u] >= q[qq.first].a && a[u] <= q[qq.first].b)
                    ans[qq.first] += b[a[u]];
            }
            else
            {
                ans[qq.first] += tmp;
            }
        }
        for (auto&v: G[u])
        {
            if (v == pre) continue;
            dfs(v, u);
        }
        modify(a[u], -b[a[u]]);
    }
    int main()
    {
        int u, v;
        while (~scanf("%d%d", &n, &Q))
        {
            init();
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
            for (int i = 1; i < n; i++)
            {
                scanf("%d%d", &u, &v);
                addedge(u, v); addedge(v, u);
            }
            for (int i = 1; i <= Q; i++)
                scanf("%d%d%d%d", &q[i].s, &q[i].t, &q[i].a, &q[i].b);
            init2();
            LCA::init();
            for (int i = 1; i <= Q; i++) LCA::adq(q[i].s, q[i].t, i);
            LCA::LCA(1);
            for (int i = 1; i <= Q; i++)
            {
                q[i].lca = LCA::ans[i];
                QQ[q[i].lca].push_back(P(i, -1));
                QQ[q[i].s].push_back(P(i, 1));
                QQ[q[i].t].push_back(P(i, 1));
            }
            dfs(1, 1);
            for (int i = 1; i < Q; i++) printf("%lld ", ans[i]);
            printf("%lld
    ", ans[Q]);
        }
    }
    

      

  • 相关阅读:
    mysql执行顺序及习题
    多表查询
    PyQt5-03-信号与槽
    PyQt5-01-安装及简单例子
    252.anaconda升级版本
    251.anaconda下载资源包慢
    250.anaconda+vscode
    61.基础语法-函数式编程
    60.基础语法-异常的处理
    59.语法基础-包
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/7419364.html
Copyright © 2011-2022 走看看