zoukankan      html  css  js  c++  java
  • bzoj4919: 大根堆

    Description

    给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点。每个点有一个权值v_i。
    你需要将这棵树转化成一个大根堆。确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i,j,如果i在树上是j的祖先,那么v_i>v_j。
    请计算可选的最多的点数,注意这些点不必形成这棵树的一个连通子树。

    Input

    第一行包含一个正整数n(1<=n<=200000),表示节点的个数。
    接下来n行,每行两个整数v_i,p_i(0<=v_i<=10^9,1<=p_i<i,p_1=0),表示每个节点的权值与父亲。

    Output

    输出一行一个正整数,即最多的点数。
    平衡树启发式合并,维护当前子树内选k个点,选出的点权最大值的最小值
    #include<bits/stdc++.h>
    const int N=200007;
    char buf[70007],*ptr=buf+70000;
    int G(){
        if(ptr-buf==70000)fread(ptr=buf,1,70000,stdin);
        return *ptr++;
    }
    int _(){
        int x=0;
        if(ptr-buf<69900){
            while(*ptr<48)++ptr;
            while(*ptr>47)x=x*10+*ptr++-48;
        }else{
            int c=G();
            while(c<48)c=G();
            while(c>47)x=x*10+c-48,c=G();
        }
        return x;
    }
    int n;
    int v[N],fa[N],q[N],ql=0,qr=0,deg[N];
    std::multiset<int>vs[N];
    typedef std::multiset<int>::iterator mit;
    int main(){
        n=_();
        for(int i=1;i<=n;++i){
            v[i]=_();
            ++deg[fa[i]=_()];
        }
        for(int i=1;i<=n;++i)if(!deg[i])q[++qr]=i;
        while(ql!=qr){
            int w=q[++ql],f=fa[w];
            mit u=vs[w].lower_bound(v[w]);
            if(u==vs[w].end())vs[w].insert(v[w]);
            else *const_cast<int*>(&*u)=v[w];
            if(f){
                if(vs[f].size()<vs[w].size())std::swap(vs[f],vs[w]);
                for(mit it=vs[w].begin(),e=vs[w].end();it!=e;++it)vs[f].insert(*it);
                vs[w].clear();
                if(!--deg[f])q[++qr]=f;
            }
        }
        printf("%d
    ",vs[1].size());
        return 0;
    }
  • 相关阅读:
    Unity中获取移动设备GPS信息
    Unity打包APP控制顶部状态栏
    Hololens概览
    webdriver中的定位模拟及实例
    selenium等待机制
    seleniumChrom无头浏览器
    selenium规避网站监测
    百度api识别验证码登录
    Pyecharts-数据可视化模块
    Selenium-浏览器兼容性测试自动化
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7122930.html
Copyright © 2011-2022 走看看