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