感谢龙哥提供的做法:
首先按照坐标排序,然后我们从前往后处理每一个点,并把这个点设为起点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;
}
本文介绍了一种通过坐标排序及并查集维护路径的方法解决区间行走问题。该方法首先按坐标排序,然后从前向后处理每个点,尽可能地扩展最大区间,使用并查集维护向左的第一个可行点。
259

被折叠的 条评论
为什么被折叠?



