zoukankan      html  css  js  c++  java
  • 2019-9-14题目

    2019-9-14题目

    accoding contest403

    https://accoding.cn/contest-ng/index.html#/403

    E

    Q:n个节点的不同形态二叉树个数

    A:

    考虑固定根节点,则左子树包含节点个数为0~n-1

    (b_n=sum_{i=0}^{n-1}b_i*b_{n-1-i})

    即为Catalan卡特兰数,(b_n=frac{C(n,2n)}{n+1})

    [LeetCode] 96. Unique Binary Search Trees 独一无二的二叉搜索树

    注意到1~n构成二叉搜索树BST的个数同样是卡特兰数,这意味着每一种二叉树的构象都唯一对应着一棵二叉搜索树(节点元素为1~n)

    B

    A:排序+小顶堆(优先队列)

    V值降序排列,然后向小顶堆逐个插入L,每次插入L后计算当前sum

    维护一个k个节点的小顶堆,只有当前影片的L大于堆顶元素时才执行真正的插入操作。但可以证明,每次都插入当前影片后调整小顶堆再pop堆顶,不影响结果的正确性。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    
    struct mv{
        int l;
        int v;
    };
    
    bool cmp(mv a,mv b){
        return a.v>b.v;
    }
    
    mv s[100006];
    
    int main(){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++){
            scanf("%d%d",&s[i].l,&s[i].v);
        }
        std::sort(s,s+n,cmp);
        std::priority_queue<int, std::vector<int>,std::greater<int> >q;//小顶堆
        long long sum=0,ans=0;
        //下面维护一个k节点的小顶堆
        for(int i=0;i<n;i++){
            /*if(i<k){
                sum+=s[i].l;
                q.push(s[i].l);
                ans=std::max(sum*s[i].v,ans);
            }
            else{
                if(s[i].l>q.top()){
                    sum+=s[i].l;
                    q.push(s[i].l);
                    sum-=q.top();
                    q.pop();
                    ans=std::max(sum*s[i].v,ans);
                }
            }*/
            sum+=s[i].l;
            q.push(s[i].l);
            if(i>=k){
                sum-=q.top();//减去堆顶
                q.pop();
            }
            ans = std::max(sum*s[i].v,ans);
            /*
            考虑新插入小顶堆的元素又被pop出的情况,这时sum依然是正确的 等于 小顶堆中所有节点之和,但s[i].v并不是这个小顶堆对应的V值,而是偏小。即这种情况会使得sum*s[i].v相比于插入之前减小。故不影响结果的正确性。
            */
        }
        printf("%lld
    ",ans);
    }
    

    J

    ref:https://www.cnblogs.com/tian-luo/p/9674289.html

    考虑完全图的MST,去掉任意一条边x之后,所得的是两个连通分量,注意到MST唯一的条件,可以知道所有连接这两个连通分量的边中,边x的权值最小且唯一,其他的边权值都必须大于x。

    所以对最小生成数中的边按升序排列,依次维护加边操作和对应连通块中点的个数就行了。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    int n;//完全图的点数
    long long sum=0;
    
    struct Edge{
        int x;
        int y;
        int z;
    }e[100006];
    
    bool cmp(Edge a,Edge b){
        return a.z<b.z;
    }
    
    long long num[100006];//每个集合对应的顶点数
    int p[100006];//并查集
    
    //并查集的查询操作
    int find(int x){
        return p[x]==x?x:p[x]=find(p[x]);
    }
    
    void init(){
        for(int i=1;i<=n;++i){
            p[i]=i;
            num[i]=1;
        }
        sum=0;
    }
    
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            init();
            for(int i=1;i<=n-1;++i){
                scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
            }
            sort(e+1,e+n,cmp);
            for(int i=1;i<=n-1;++i){
                int u=find(e[i].x);
                int v=find(e[i].y);
                sum+=(e[i].z+1)*(num[u]*num[v]-1);//坑:这里的乘法操作会溢出int,需要将num[]数组类型设为long long
                sum+=e[i].z;
                p[u]=v;
                num[v]+=num[u];
            }
            printf("%lld
    ",sum);
        }
    }
    
    int ~ 2e9 10位数
    long long ~ 9e18 19位数
    unsigned int ~ 4e9 10位数
    unsigned long long ~ 1e19 20位数
    

    D

    Q:并查集

  • 相关阅读:
    The&nbsp;library&nbsp;contains&nbsp;native&nbsp;libr…
    DHCP configurations in Ubuntu
    如何编译Linux Kernel
    Rsync 使用指南
    Linux下用semaphore来做进程间互斥
    How to generate patch file?
    PS3MediaServer(用于PS3的DLNA server) 在Ubuntu 9.10上的安装和配置
    嘉猪的最爱 PS3
    梦寐以求的SPL总冠军,KT你赢了
    PLU space in 优酷
  • 原文地址:https://www.cnblogs.com/cbw052/p/11524223.html
Copyright © 2011-2022 走看看