• 【USACO17JAN】Promotion Counting P


    题目链接

    如果只有一条链,可以直接离散化上权值树状数组一遍过。

    在树上,考虑怎么消除不同子树之间的影响。

    略微思考可以得出,可以在递归子树之前先求一遍询问前缀存下来,回溯回来再求一遍询问前缀,减一下得到子树新增的前缀。再用子树大小减一下,就是当前子树的答案。

    代码(100分):

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #define IL inline
    #define RG register
    #define _1 first
    #define _2 second
    using namespace std;
    const int N=1e5;
    
        int n,p[N+3];
        
    struct Edge{
        int to,nxt;
    }e[N+3];
        int top,h[N+3];
    
    IL void gra_init(){
        top=-1;
        memset(h,-1,sizeof h);
    }
    
    IL void link(int u,int v){
        top++;;
        e[top].to=v;
        e[top].nxt=h[u];
        h[u]=top;
    }
    
        int k,a[N+3];
    
    IL int sol(int x){
        int l=1,r=k,mid,ans;
        while(l<=r){
            mid=(l+r)>>1;
            if(x<=a[mid]){
                r=mid-1;    ans=mid;
            }
            else 
                l=mid+1;
            
        }
        return ans;
        
    }
    
    IL void discrete(){
        memcpy(a,p,sizeof p);
        sort(a+1,a+n+1);
        k=1;
        for(int i=2;i<=n;i++)
        if(a[i]!=a[i-1])
            a[++k]=a[i];
        for(int i=1;i<=n;i++)
            p[i]=sol(p[i]);
        
    }
    
        int s[N+3];
    
    IL int lowbit(int x){
        return x&(-x);
    }
    
    IL void mdf(int p,int x){
        for(;p<=k;p+=lowbit(p))
            s[p]+=x;
    }
    
    IL int qry(int p){
        int ret=0;
        for(;p;p-=lowbit(p))
            ret+=s[p];
        return ret;
    }
    
        int ans[N+3];
    
    int dfs(int u){
        int tmp=qry(p[u]),cnt=0;
        for(int i=h[u];~i;i=e[i].nxt)
            cnt+=dfs(e[i].to);
            
        cnt++;
        mdf(p[u],1);
        ans[u]=cnt-qry(p[u])+tmp;
        return cnt;
        
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        gra_init();
        for(int i=2;i<=n;i++){
            int x;    scanf("%d",&x);
            link(x,i);
            
        }
        
        discrete();
        memset(s,0,sizeof s);
        dfs(1);
        for(int i=1;i<=n;i++)
            printf("%d
    ",ans[i]);
    
        return 0;
    
    }
    View Code
  • 相关阅读:
    Axure chrome 安装及已损坏的解决方法
    Ubuntu16.04上使用git
    ubuntu初探
    nginx入门笔记
    更改element-UI按钮默认样式
    js深拷贝与浅拷贝的区别及实现
    安装mysql-python的遇到的问题
    facebook atc弱网环境搭建和踩坑总结
    验证码识别 Tesseract的简单使用和总结
    selenium 基础(一)
  • 原文地址:https://www.cnblogs.com/Hansue/p/12936840.html
Copyright © 2020-2023  润新知