4099: [Usaco2015 Open]Trapped in the Haybales 并查集+思路题

本文介绍了一种通过坐标排序及并查集维护路径的方法解决区间行走问题。该方法首先按坐标排序,然后从前向后处理每个点,尽可能地扩展最大区间,使用并查集维护向左的第一个可行点。

感谢龙哥提供的做法:
首先按照坐标排序,然后我们从前往后处理每一个点,并把这个点设为起点st,然后尽量左左右右走走扩展出最大的区间,如果到头了说明可行,否则说明st>r这个区间的每个点都不可能走出去,用并查集维护向左的第一个可行的点,并且将路径上的标记传递一下。
好像卡到了rank1?不到五分钟就被yzy大爷艹翻了

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
using namespace std;
int n,ans;
int flag[N],f[N];
struct node {int s,l;} b[N];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline bool operator<(node a,node b)
{
    return a.l<b.l;
}
int find(int x)
{
    if (f[x]!=x)
    {
        f[x]=find(f[x]);
        if (flag[x]==1) flag[f[x]]=1;
    }
    return f[x];
}
inline bool check(int st)
{
    int l=st,r=st+1;
    while (l&&r<=n)
    {
        if (b[r].l-b[l].l>b[l].s) f[l]=find(l-1),l=find(l-1);
        else if (b[r].l-b[l].l>b[r].s) r++;
        else break;
        if (flag[l]==1) return 1;
    }
    if (l<1||r>n) return 1;
    for (int i=st;i<r;i++) flag[i]=-1,f[i]=l;
    return 0;
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) b[i].s=read(),b[i].l=read();
    sort(b+1,b+n+1);
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<n;i++)
    {
        if (flag[i]==-1)
        {
            ans+=b[i+1].l-b[i].l;
            continue;
        }
        if (!check(i)) ans+=b[i+1].l-b[i].l;
        else flag[find(i)]=1;
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值