zoukankan      html  css  js  c++  java
  • 线段树合并与*

    线段树合并

    BZOJ4756(权限题><)

    题意

    给一棵树,每个节点都有一个值,求其子树中值比他大的个数

    分析

    线段树合并

    先将点离散化,动态开线段树,依靠dfs序回溯的时候实现查询子树和合并线段树的操作即可

    合并的时候注意要将子树信息更新上去直接加到子数上即可,树的结构是一样的

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    int a[maxn], b[maxn];
    int lson[maxn], rson[maxn];
    int tree[maxn];
    int root[maxn];
    int cnt = 0;
    int n;
    int ans[maxn];
    vector<int>G[maxn];
    int temp;
    
    int newnode()
    {
        ++cnt;
        lson[cnt]=rson[cnt]=0;
        return cnt;
    }
    
    void push_up(int x)
    {
        tree[x]=tree[lson[x]]+tree[rson[x]];
    }
    
    int build(int x, int l ,int r,int num)
    {
        if(!x)
            x=newnode();
        if(l==r)
        {
            tree[x]=1;
            return x;
        }
        int mid = (l+r)/2;
        if(num<=mid) lson[x] = build(lson[x], l, mid, num);
        else   rson[x] = build(rson[x], mid+1, r, num);
        push_up(x);
        return x;
    }
    
    int query(int x, int l, int r, int ql, int qr)
    {
        if(ql<=l && qr>=r)
            return tree[x];
        int mid = (l+r)/2;
        int ans = 0;
        if(ql<=mid && lson[x]) ans+=query(lson[x], l, mid, ql, qr);
        if(qr>mid && rson[x])  ans+=query(rson[x], mid+1,r, ql,qr);
        return ans;
    }
    
    int mercy(int root1, int root2)
    {
        if(!root1) return root2;
        if(!root2) return root1;
        lson[root1] = mercy(lson[root1], lson[root2]);
        rson[root1] = mercy(rson[root1], rson[root2]);
        tree[root1] += tree[root2];
        return root1;
    }
    
    void dfs(int now, int fa)
    {
        int len = G[now].size();
        for(int i = 0; i < len; i++)
        {
            int k = G[now][i];
            if(k == fa)
                continue;
            dfs(k, now);
            ans[now]+=query(root[k],1,temp,min(a[now]+1,temp),temp);
            mercy(root[now], root[k]);
        }
    }
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            b[i]=a[i];
        }
        sort(b+1, b+n+1);
        temp = unique(b+1, b+n+1)-b-1;
        for(int i = 1; i <=n; i++)
        {
            a[i] = lower_bound(b+1, b+temp+1,a[i])-b;
        }
        int x;
        for(int i = 2; i <= n;i++)
        {
            scanf("%d", &x);
            G[i].push_back(x);
            G[x].push_back(i);
        }
        for(int i = 1; i <= n; i++)
        {
            root[i] = build(root[i], 1 , temp, a[i]);
        }
        dfs(1, 1);
        for(int i = 1; i <= n; i++)
        printf("%d ", ans[i]);
        return 0;
    }
    View Code
    要么优秀要么生锈
  • 相关阅读:
    数组的完全随机排列算法
    css超出2行部分省略号...
    前端面试题精华总结
    在地址栏输入网址后页面是如何呈现的?
    document.write和innerHTML的区别
    js运算符单竖杠“|”与“||”的用法和作用介绍
    border:none与border:0的区别
    如何实现浏览器内多个标签页之间的通信?
    js 关键字 in 的使用方法
    msyql: navicat 连接时msyql遇到的问题
  • 原文地址:https://www.cnblogs.com/Superwalker/p/7851535.html
Copyright © 2011-2022 走看看