zoukankan      html  css  js  c++  java
  • 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162

    题意:给出一棵树的链接方法,每个点都有一个数字,询问U-》V节点经过所有路径中l < = x < = r的数字和

    解法:主席树维护区间和,树剖查询,复杂度nloglog。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5+5;
    const int maxm = 40*maxn;
    typedef long long LL;
    int T[maxn];
    int lson[maxm],rson[maxm];
    LL sum[maxm];
    int clk,M;
    int newnode(){
        clk++;
        lson[clk]=rson[clk]=sum[clk]=0;
        return clk;
    }
    void update(int &now, int pre, int L, int R, int pos, int val)
    {
        now = newnode();
        lson[now] = lson[pre];
        rson[now] = rson[pre];
        sum[now] = sum[pre] + val;
        if(L!=R){
            int mid=(L+R)>>1;
            if(pos<=mid) update(lson[now],lson[pre],L,mid,pos,val);
            else update(rson[now],rson[pre],mid+1,R,pos,val);
        }
    }
    LL query(int rt, int L, int R, int l, int r){
        if(l<=L&&R<=r){
            return sum[rt];
        }
        else{
            int mid = (L+R)>>1;
            LL ret = 0;
            if(l <= mid) ret += query(lson[rt], L, mid, l, r);
            if(mid < r) ret += query(rson[rt], mid+1, R, l, r);
            return ret;
        }
    }
    struct edge{
        int to,next;
    }E[maxn*2];
    int head[maxn],edgecnt,tim;
    int siz[maxn],top[maxn],son[maxn],dep[maxn];
    int fa[maxn],tid[maxn],Rank[maxn],val[maxn];
    void init(){
        edgecnt=tim=0;
        memset(head,-1,sizeof(head));
        memset(son,-1,sizeof(son));
        clk=M=0;
        lson[clk]=rson[clk]=sum[clk]=0;
    }
    void add(int u, int v){
        E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
    }
    void dfs1(int u, int pre, int d){
        dep[u]=d;
        fa[u]=pre;
        siz[u]=1;
        for(int i=head[u];~i;i=E[i].next){
            int v=E[i].to;
            if(v!=pre){
                dfs1(v,u,d+1);
                siz[u]+=siz[v];
                if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
            }
        }
    }
    void dfs2(int u, int tp){
        top[u]=tp;
        tid[u]=++tim;
        Rank[tid[u]]=u;
        if(son[u]==-1) return;
        dfs2(son[u],tp);
        for(int i=head[u];~i;i=E[i].next){
            int v=E[i].to;
            if(v!=son[u]&&v!=fa[u]){
                dfs2(v,v);
            }
        }
    }
    int LCA(int u, int v)
    {
        int ret;
        while(true)
        {
            if(top[u] == top[v])
            {
                ret = dep[u] < dep[v] ? u : v;
                break;
            }
            else if(dep[top[u]] > dep[top[v]])
                u = fa[top[u]];
            else v = fa[top[v]];
        }
        return ret;
    }
    int t[maxn];
    LL query(int u, int v, int a, int b)
    {
        a = lower_bound(t + 1, t + 1 + M, a) - t - 1;
        b = upper_bound(t + 1, t + 1 + M, b) - t - 1;
        if(b == 0)
            return 0;
        LL ret = 0;
        while(top[u] != top[v])
        {
            if(dep[top[u]] < dep[top[v]])
                swap(u, v);
            ret += query(T[tid[u]], 1, M, 1, b);
            ret -= query(T[tid[top[u]] - 1], 1, M, 1, b);
            if(a)
            {
                ret -= query(T[tid[u]], 1, M, 1, a);
                ret += query(T[tid[top[u]] - 1], 1, M, 1, a);
            }
            u = fa[top[u]];
        }
        if(dep[u] < dep[v])
            swap(u, v);
        ret += query(T[tid[u]], 1, M, 1, b);
        ret -= query(T[tid[v] - 1], 1, M, 1, b);
        if(a)
        {
            ret -= query(T[tid[u]], 1, M, 1, a);
            ret += query(T[tid[v] - 1], 1, M, 1, a);
        }
        return ret;
    }
    int main()
    {
        int n,m;
        while(~scanf("%d %d",&n,&m))
        {
            init();
            for(int i=1; i<=n; i++){
                scanf("%d", &val[i]);
                t[i]=val[i];
            }
            for(int i=1; i<n; i++){
                int u,v;
                scanf("%d %d", &u,&v);
                add(u, v);
                add(v, u);
            }
            dfs1(1,0,0);
            dfs2(1,1);
            sort(t+1,t+n+1);
            M = unique(t+1, t+n+1)-t-1;
            for(int i=1; i<=n; i++) val[i] = lower_bound(t+1, t+1+M, val[i])-t;
            for(int i=1; i<=n; i++){
                T[i] = T[i-1];
                update(T[i],T[i],1,M,val[Rank[i]],t[val[Rank[i]]]);
            }
            for(int i=1; i<=m; i++){
                int u,v,x,y;
                scanf("%d %d %d %d", &u,&v,&x,&y);
                LL ret = query(u,v,x,y);
                printf("%lld", ret);
                if(i == m){
                    printf("
    ");
                }
                else{
                    printf(" ");
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    GitLab基本用法
    SSH免密登录详解
    一文搞懂GitLab安装部署及服务配置
    初识:LevelDB
    Jenkins安装与Gitlab项目部署详解
    CentOS7的安装和配置
    C/C++语言的学习方向
    C语言atoi函数
    C语言整数的取值范围
    C语言scanf函数
  • 原文地址:https://www.cnblogs.com/spfa/p/7418304.html
Copyright © 2011-2022 走看看