zoukankan      html  css  js  c++  java
  • 【BZOJ】4756: [Usaco2017 Jan]Promotion Counting

    【题意】带点权树,统计每个结点子树内点权比它大的结点数。

    【算法】线段树合并

    【题解】对每个点建权值线段树(动态开点),DFS中将自身和儿子线段树合并后统计。

    注意三个量tot,cnt,tots,细心查错。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=200010;
    int n,first[maxn],cnt,tot,tots,root[maxn],a[maxn],b[maxn],ans[maxn];
    struct edge{int v,from;}e[maxn*2];
    void ins(int u,int v){tots++;e[tots].v=v;e[tots].from=first[u];first[u]=tots;}
    struct cyc{int l,r,sum;}t[maxn*10];
    void insert(int l,int r,int &x,int y){
        if(!x)x=++cnt;t[x].sum++;
        if(l==r)return;//
        int mid=(l+r)>>1;
        if(y<=mid)insert(l,mid,t[x].l,y);
        else insert(mid+1,r,t[x].r,y);
    }
    int merge(int x,int y){
        if(!x||!y)return x^y;//1
        t[x].l=merge(t[x].l,t[y].l);
        t[x].r=merge(t[x].r,t[y].r);//2
        t[x].sum=t[t[x].l].sum+t[t[x].r].sum;//3
        return x;
    }
    int ask(int left,int right,int k,int l,int r){
        if(l<=left&&right<=r)return t[k].sum;
        else{
            int mid=(left+right)>>1,sum=0;
            if(l<=mid)sum=ask(left,mid,t[k].l,l,r);
            if(r>mid)sum+=ask(mid+1,right,t[k].r,l,r);
            return sum;
        }
    }
    void dfs(int x){
        insert(1,tot,root[x],a[x]);
        for(int i=first[x];i;i=e[i].from){
            dfs(e[i].v);
            root[x]=merge(root[x],root[e[i].v]);
        }
        if(a[x]<tot)ans[x]=ask(1,tot,root[x],a[x]+1,tot);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        for(int i=2;i<=n;i++){
            int fa;scanf("%d",&fa);
            ins(fa,i);
        }
        sort(b+1,b+n+1);tot=n;
        tot=unique(b+1,b+tot+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
        dfs(1);
        for(int i=1;i<=n;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    树莓派摄像头测试
    mqtt搭建基础教程()
    win10开始图标点击无效
    【python学习笔记:Django】7.数据库模型浅析
    【python学习笔记:Django】6.MySQL那些坑
    Ubuntu分区扩容
    Wine的中文显示与字体设置
    从有序矩阵M x N中找出是否包含某一个数,要求时间复杂度为O(M+N)
    之字形打印矩阵
    双向链表反转
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7724293.html
Copyright © 2011-2022 走看看