zoukankan      html  css  js  c++  java
  • 疫情控制(NOIP2012)庆祝2012满贯!٩(๑•◡-๑)۶ⒽⓤⒼ

    丧病至极的D2T3啊!

    好吧~

    先放个传送门~

    原题传送门

    好吧,这道题呢。。

    根据题意我们可以很明显的看出来

    军队往上走的越多(在没到根节点之前),效益一定越大。。

    所以可以分情况讨论:

    对于无法走到根节点的军队,我们让他走到他能走到的离根节点最近的点

    对于可以走到根节点,而且还有剩余时间的点,我们把它记到一个数组里【queen】。

    由于第一层(也就是根节点)是无法停留的。

    所以我们把能走到根节点的点全部扔到叶子节点还未被覆盖的第二层的点上。

    由于结果的单调性,我们可以二分答案。

    接下来是重点。

    由于queen[]中的所有点都可以到任意一个第二层的点。

    所以我们可以设想一个贪心。

    把时间剩余最多的点给距离根节点最长的第二层的点。

    如果出现找不到的情况,或者不满足的情况,

    那么就往大二分,不然就往小二分;

    最后的l就是答案啦!

    接下来是小贴士:

    1、如果你偷懒,不手写比较,而直接用multiset的话,en~你会TLE

    2、如果不手打快排的话,你也很容易TLE

    3、如果你不打快读的话,你很可能TLE

    恩,我三种都没打~

    但是过了~

    怎么过的呢?~

    我们先来看看题目

    0<w<10^9..

    好大。。

    对不对。

    但是如果用这个算法的话

    时间复杂度为(nlog^2n)

    那么是不是看上去不会炸?

    可是二分的右端点怎么办?

    有的人直接50000*10^9;

    然后不写上面的优化全炸TLE

    我机智的写了10^8.。

    好吧,那是RP好,考场上这么写。。你就等死吧。

    下面贴代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<set>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int n,num=0,m,nownode;
    int jd[50001];
    int head[50001];
    int leaf[50001];
    int son[50001];
    int sontree[50001];
    bool visit[50001];
    int queen[50001];
    multiset<int> S;  
    multiset<int>::iterator it; 
    int dist[50001][17];
    int cnt[50001];
    int fa[50001][17];
    int Min[50001];
    struct duoyu{
        int opt,timen;
    }a[50001];
    struct edge{
        int next,to,value;
    }g[100001];
    void ins(int x1,int y1,int v1){
        g[++num].next=head[x1];
        head[x1]=num;
        g[num].to=y1;
        g[num].value=v1;
    }
    void dfs(int u)
    {
        sontree[u]=nownode;
        visit[u]=true;
        bool flag=1;
        for(int i=head[u];i;i=g[i].next){
            int v=g[i].to;
            if(!visit[v])
            {
                flag=false;
                fa[v][0]=u;
                dist[v][0]=g[i].value;
                if(u==1)nownode=v;
                dfs(v);
            }
        }
        leaf[u]=flag;
    }
    void findleaf(int x,int father){
        if(cnt[x])return;
        if(leaf[x])
        {
            son[nownode]=true;
            return; 
        }
        for(int i=head[x];i;i=g[i].next)
        {
            int v=g[i].to;
            if(v!=father)
            {
                if(x==1)nownode=v;
                findleaf(v,x);
            }    
        }
    }
    bool check(long long tme){
        S.clear();
        int arm=0;
        memset(son,0,sizeof(son));
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=m;i++)
        {
            long long len=tme;
            int jundui=jd[i];
            for(int j=16;j>=0;j--)
                if(dist[jundui][j]<=len&&fa[jundui][j])
                {
                        len-=dist[jundui][j];
                        jundui=fa[jundui][j];    
                }
            if(jundui==1)
            {
                a[++arm].opt=jd[i];
                a[arm].timen=len;
            }
            else
            cnt[jundui]++;
        }
        findleaf(1,0);
        int tt=0;    
        for(int i=1;i<=n;i++)Min[i]=-1;
        for(int i=1;i<=arm;i++)
        {
            int q=sontree[a[i].opt];
            if(son[q]){
                if(Min[q]==-1||a[Min[q]].timen>a[i].timen)
                Min[q]=i;
            }
        }
        for(int i=1;i<=n;i++)
            if(son[i]&&Min[i]!=-1&&a[Min[i]].timen<dist[i][0])
            a[Min[i]].timen=-1;
            else if(son[i]) queen[++tt]=dist[i][0];
        sort(queen+1,queen+tt+1);
        for(int i=1;i<=arm;i++)
        {
            if(a[i].timen!=-1) S.insert(a[i].timen);
        }
        for(int i=tt;i>=1;i--)
        {
            if(S.lower_bound(queen[i])==S.end()) return false;    
            it=S.lower_bound(queen[i]);
            S.erase(it);    
        }
        return true;
    }
    void addedge(int x1,int y1,int v1)
    {
        ins(x1,y1,v1);ins(y1,x1,v1);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y,v;
            scanf("%d%d%d",&x,&y,&v);
            addedge(x,y,v);
        }
        dfs(1);
        for(int j=1;j<=16;j++)
        for(int i=1;i<=n;i++)
        {
            fa[i][j]=fa[fa[i][j-1]][j-1];
            dist[i][j]=dist[i][j-1]+dist[fa[i][j-1]][j-1];
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d",&jd[i]);    
        long long L=1,R=500000;
        long long ans=-1;  
        while(L<=R){
        long long mid=(L+R)>>1;
        if(check(mid)){R=mid-1;ans= mid;}else L=mid+1;    
        }
        printf("%lld",ans);
        return 0;
    }

    没错!我最后改成了50万。。!过了!233

    可是还是排在倒一(囧。。)

    前排膜拜各路大神啊。。

    听说拓补+倍增就100ms+..

    蒟蒻滚粗。。(%%%zxyer)

  • 相关阅读:
    国外物联网平台初探(一) ——亚马逊AWS IoT
    国内物联网平台初探(七) ——Ablecloud物联网自助开发和大数据云平台
    国内物联网平台初探(六) ——庆科云FogCloud
    国内物联网平台初探(五) ——机智云IoT物联网云服务平台及智能硬件自助开发平台
    国内物联网平台初探(四) ——京东微联
    国内物联网平台初探(三) ——QQ物联·智能硬件开放平台
    国内物联网平台初探(二) ——阿里云物联网套件
    国内物联网平台初探(一) ——百度物接入IoT Hub
    iOS开发技巧
    【Oracle】RAC添加新节点
  • 原文地址:https://www.cnblogs.com/ghostfly233/p/6842081.html
Copyright © 2011-2022 走看看