zoukankan      html  css  js  c++  java
  • [Usaco2006 Open]County Fair Events 参加节日庆祝

    原题链接https://www.lydsy.com/JudgeOnline/problem.php?id=1664

    可以发现的是,如果参加了节日(i)之后可以参加节日(j),当且仅当(i)节日的结束时间(l[i])小于等于(j)节日的开始时间(t[j])。那么我们对于每个(i),可以从(i)出发向每个合法的(j)连一条边,表示参加完(i)之后可以接着参加(j)

    题目要求最多参加几场节日,那么我们设边权为1,在我们建出的(DAG)上算出最长路的长度就是答案。那么我们可以建一个超级源,用拓扑排序进行(dp)

    建图的时间复杂度最坏为(O(frac{N(N-1)}{2})),图的规模也是(frac{N(N-1)}{2}),所以拓扑排序的复杂度和建图一致。

    不过我们可以整一个玄学优化:我们可以不用对于每个(i)都枚举完(1)$n$所有节日。我们先把节日按照开始时间$t$从小到大进行排序,然后对于第$i$个节日,我们二分查找第一个开始时间大于等于$i$的结束时间的节日$j$,那么我们把$i$连向$j$(n)即可。这样一般就不用枚举完1~n所有数。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #define maxn 10010
    using namespace std;
     
    inline int read(){
        register int x(0),f(1); register char c(getchar());
        while(c<'0'||'9'<c){ if(c=='-') f=-1; c=getchar(); }
        while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
     
    struct node{ int t,l,id; }a[maxn];
    vector<int> to[maxn];
    int n,tmp[maxn];
    int ind[maxn],dp[maxn],ans;
     
    inline bool cmp(const node &x,const node &y){ return x.t<y.t; }
     
    inline int binary(const int &val){
        if(a[n].t<val) return -1;
        int l=1,r=n,mid;
        while(l<r){
            mid=l+r>>1;
            if(a[mid].t<val) l=mid+1;
            else r=mid;
        }
        return l;
    }
     
    queue<int> q;
    inline void topo(){
        q.push(0),dp[0]=0;
        while(q.size()){
            int u=q.front(); q.pop();
            for(register int i=0;i<to[u].size();i++){
                int v=to[u][i];
                dp[v]=max(dp[v],dp[u]+1),ind[v]--;
                if(!ind[v]) q.push(v);
            }
        }
    }
     
    int main(){
        n=read();
        for(register int i=1;i<=n;i++) a[i].t=read(),a[i].l=read(),a[i].id=i;
        sort(a+1,a+1+n,cmp);
         
        for(register int i=1;i<=n;i++){
            int end=a[i].l+a[i].t;
            int j=binary(end);
            if(j==-1) continue;
            for(register int k=j;k<=n;k++){
                to[a[i].id].push_back(a[k].id),ind[a[k].id]++;
            }
        }
        for(register int i=1;i<=n;i++) to[0].push_back(i),ind[i]++;
         
        topo();
        for(register int i=1;i<=n;i++) ans=max(ans,dp[i]);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    2019牛客暑期多校训练营(第三场)B题、H题
    2019牛客暑期多校训练营(第四场)k题、j题
    Manacher算法 & Palindrome
    HDU 3336——Count the string
    判断一个点是否在三角形内
    P1052 过河
    P1353 [USACO08JAN]跑步Running
    hdu 1686 Oulipo
    Cyclic Nacklace HDU
    高精地图技术分析
  • 原文地址:https://www.cnblogs.com/akura/p/11309779.html
Copyright © 2011-2022 走看看