4099: [Usaco2015 Open]Trapped in the Haybales|并查集|乱搞

暴力大法好,乱搞出奇迹!!
从左到右枚举两个草包之间的空隙,找从这个空隙最左边的最右边分别能到的最远的地方,因为是从左到有枚举的,所以如果到了前一个草包之间的空隙,那么他到达的最远的左端点肯定可以让当前的空隙来更新,然后维护最远到达的左区间可以用到并查集的思想。右区间就直接暴力
如果从当前的间隙走不出去,那么从当前间隙走到的间隙也都走不出去,可以处理一下
似乎卡爆了某位神犇成了 rank1

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#define pa pair<int,int>
#define ll long long
#define N 100005
#define mx 1e9
using namespace std;
int sc()
{
    int i=0,f=1; char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
    return i*f;
}
struct W{int p,l;}a[N];
int n,l[N],r[N],ans,sum=0,flag[N];
bool cmp(W a,W b){return a.p<b.p;}
int find(int x)
{
    return l[x]==x?x:l[x]=find(l[x]);
}
int main()
{
    n=sc();
    for(int i=1;i<=n;i++)
        a[i].l=sc(),a[i].p=sc();
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)l[i]=r[i]=i;
    for(int i=1;i<n;i++)
    {
        if(flag[i]==1)
        {
            ans+=a[i+1].p-a[i].p;
            continue;
        }
        while(1)
        {
            if(!l[i]||r[i]==n)break;
            int L=a[r[i]+1].p-a[l[i]].p;
            if(L>a[l[i]].l)
            {
                l[i]--;
                l[i]=find(l[i]);
                r[i]=max(r[i],r[l[i]]);
            }
            else if(L>a[r[i]+1].l)
                r[i]++;
            else break;
        }
        if(l[i]&&r[i]!=n)
        {
            ans+=a[i+1].p-a[i].p;
            for(int j=i;j<=r[i];j++)
                l[j]=i,flag[j]=1;
        }
    }
    cout<<ans;
    return 0;
}

你可能感兴趣的:(并查集)