BZOJ-1635: [Usaco2007 Jan]Tallest Cow 最高的牛

[文章目录]

Description

有n(1 <= n <= 10000)头牛从1到n线性排列,每头牛的高度为h[i] (1 <= i <= n),现在告诉你这里面的牛的最大高度为maxH,而且有r组关系,每组关系输入两个数字,假设为a和b,表示第a头牛能看到第b头牛,能看到的条件是a, b之间的其它牛的高度都严格小于min(h[a], h[b]),而h[b] >= h[a]

差分约束,分块优化建图。(话说可以线段树优化啊)
然而我做矬了,发现给你的区间(a,b)互相不会包含。
那么直接将区间差分,考虑每个点被多少个区间包含,计算权值即可。

#include <cmath>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,h,m,b[11000];
int head[11000],to[3100000],nxt[3100000],f[3100000],cnt;
int dis[11000];
bool vis[11000];
queue<int>q;
inline void add(int x,int y,int z)
{
    to[++cnt]=y; nxt[cnt]=head[x];
    head[x]=cnt; f[cnt]=z;
}
void spfa()
{
    for(int i=1;i<=b[n];++i) q.push(i),vis[i]=1,dis[i]=h;
    int x;
    while(!q.empty())
    {
        x=q.front(); q.pop(); vis[x]=0;
        for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]>dis[x]+f[i])
        {
            dis[to[i]]=dis[x]+f[i];
            if(!vis[to[i]]) q.push(to[i]),vis[to[i]]=1;
        }
    }
}

int main()
{
    scanf("%d%*d%d%d",&n,&h,&m);
    int blo=(int)sqrt((double)n)+2;
    b[0]=n;
    for(int i=1;i<=n;++i)
    {
        if(i%blo==1) b[i]=b[i-1]+1;
        else b[i]=b[i-1]; 
        add(b[i],i,0);
    }
    int x,y,l,r,L,R;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&x,&y);
        add(y,x,0); L=min(x,y)+1; R=max(x,y)-1;
        for(l=L;l<=R;++l)
        {
            if(l%blo!=1) add(x,l,-1);
            else break;
        }
        for(r=R;r>=l;--r)
        {
            if(r%blo!=0) add(x,r,-1);
            else break;
        }
        if(l<r) for(int j=b[l];j<=b[r];++j) add(x,j,-1);
    }
    spfa();
    for(int i=1;i<=n;++i) printf("%d\n",dis[i]);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注