zoukankan      html  css  js  c++  java
  • 20171129校内训练

    我们把ai向i连边。样例连出来的图是这样的:

    然后,我们可以发现,对于每个节点,它需要和它所有的子节点都比赛一场,然后输给它的父亲节点。

    用f[i]表示以i为子树的所有节点全部比赛完需要的最少时间。

    如何更新f[i]?第i号节点要和它所有的子节点比赛一场,显然,它应该先和它的子节点所用时间最短的,所用时间第二的......这样打,这样时间不会浪费

    即我们把它的子节点的f值排序,用一个变量now记录此时所用时间,遍历每一个节点,若当前节点能打(即它的最少时间<=now),那么就打(now++),否则只能等到它的最小时间再打(now=f[]+1)。f[i]=now。

    注意:在dfs中,这一层递归保存的全局变量容易被后一层的递归保存的给替换。就像这份代码中的:

    for(int i=h[x];i;i=nxt[i])dfs(to[i]);
    for(int i=h[x];i;i=nxt[i])a[++tot]=f[to[i]];

    原先写成for(int i=h[x];i;i=nxt[i]){dfs(to[i]);a[++tot]=f[to[i]];}    a数组就被替换了。

    解决办法1:不开全局。2:像这份代码一样,先递归好下一层的,再对这一层的进行操作。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int q[100100];
    int h[101001],nxt[101001],to[101001],k=0;
    int f[101001],a[100100];
    void ins(int u,int v){nxt[++k]=h[u];to[k]=v;h[u]=k;}
    void dfs(int x)
    {
        int tot=0;
        for(int i=h[x];i;i=nxt[i])dfs(to[i]);
        for(int i=h[x];i;i=nxt[i])a[++tot]=f[to[i]];
        if(tot==0){f[x]=0;return;}
        sort(a+1,a+tot+1);
        int Max=a[1]+1;
        for(int i=2;i<=tot;i++)if(a[i]+1<=Max)Max++;else Max=a[i]+1;
        f[x]=Max;
    }
    int main()
    {
    //    freopen("contest.in","r",stdin);freopen("contest.out","w",stdout);
        int n;scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            int a;scanf("%d",&a);
            ins(a,i);
        }
        dfs(1);printf("%d",f[1]);
        return 0;
    }
    View Code

    首先,根据调和级数,总拍摄点只有大约nlogn个。

    对于每个k,我们统计拍不到的植被数,拍不到的植被会被包含在相邻两个拍摄点(开区间)或边界与拍摄点(左开右闭(右开左闭)区间)之间。

    即黑色的点为拍摄点,红色的点为边界,黄色的区间就无法被拍到,绿色的区间就能被拍到。

    然后,原题转化成,给出m个区间[l,r],给出一些询问,询问一个区间[a,b],有多少个区间[l,r]满足l>=a&&r<=b。

    简单的二维偏序问题。爱怎么做怎么做。

    这是拍不到的植被数,答案为总数-拍不到的植被数

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    struct xxx{
        int l,r,type,id;
    }q[2000000],tmp[2000000];
    int ans[2000000];
    bool cmp(xxx a,xxx b){return a.l!=b.l?a.l>b.l:a.type>b.type;}
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=(l+r)/2;
        cdq(l,mid);cdq(mid+1,r);
        int i=l,j=mid+1,tot=0,sum=0;
        while(i<=mid&&j<=r)
        {
            if(q[i].r<=q[j].r){tmp[++tot]=q[i];sum+=q[i].type;i++;}
            else {ans[q[j].id]+=sum;tmp[++tot]=q[j];j++;}
        }
        while(i<=mid)tmp[++tot]=q[i++];
        while(j<=r){ans[q[j].id]+=sum;tmp[++tot]=q[j++];}
        for(int i=l;i<=r;i++)q[i]=tmp[i-l+1];
    }
    int main()
    {
        freopen("photo.in","r",stdin);freopen("photo.out","w",stdout);
        int n,m,tot=0;scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            tot++;scanf("%d%d",&q[tot].l,&q[tot].r);q[tot].id=0;q[tot].type=1;
        }
        for(int i=1;i<=n;i++)
        {
            int k=1;
            for(;k*i<=n;k++)
            {
                tot++;q[tot].l=(k-1)*i+1;q[tot].r=k*i-1;q[tot].type=0;q[tot].id=i;
            }
            tot++;q[tot].l=(k-1)*i+1;q[tot].r=n;q[tot].type=0;q[tot].id=i;
        }
        sort(q+1,q+tot+1,cmp);cdq(1,tot);
        for(int i=1;i<=n;i++)printf("%d
    ",m-ans[i]);
        return 0;
     } 
    View Code

  • 相关阅读:
    Golang的标准命令简述
    Golang的环境安装
    初识Golang编程语言
    基于Ambari的WebUI部署Hive服务
    基于Ambari Server部署HDP集群实战案例
    HBase shell常用命令总结
    HBase完全分布式集群搭建
    HBase工作原理概述
    面向对象-接口(interface)实战案例
    myBatis 简介
  • 原文地址:https://www.cnblogs.com/lher/p/7944785.html
Copyright © 2011-2022 走看看