题面:
题意:
给定正整数
n
n
n 和起始位置
s
s
s。
n
n
n 表示有
n
n
n 个杆子,每个杆子由属性
(
x
i
,
h
i
)
(x_i,h_i)
(xi,hi) 构成,表示在
x
i
x_i
xi 处有一根高度为
h
i
h_i
hi 的杆子。初始时在
s
s
s 杆子处。
每爬到一个杆子(途径不算)我就会把这个杆子扔掉。
从当前位置要去的下一个杆子符合以下条件:假设当前在杆子
i
i
i 处。
(1)当前还在场上的杆子。
(2)选择
h
j
−
∣
x
i
−
x
j
∣
h_j-|x_i-x_j|
hj−∣xi−xj∣ 最大的杆子。
(3)如果有多个
h
j
−
∣
x
i
−
x
j
∣
h_j-|x_i-x_j|
hj−∣xi−xj∣ 最大的杆子,选择
∣
x
i
−
x
j
∣
|x_i-x_j|
∣xi−xj∣ 最小的杆子。
(4)如果有多个
h
j
−
∣
x
i
−
x
j
∣
h_j-|x_i-x_j|
hj−∣xi−xj∣ 最大的杆子,且有多个
∣
x
i
−
x
j
∣
|x_i-x_j|
∣xi−xj∣ 最小的杆子。选择最左侧的杆子。
题解:
考虑对于某一个确定的
x
i
x_i
xi,如果
x
i
<
=
x
j
x_i<=x_j
xi<=xj,那么条件(2),(3)转化为
m
a
x
(
h
j
−
x
j
)
,
m
i
n
(
x
j
)
max(h_j-x_j),min(x_j)
max(hj−xj),min(xj)。如果
x
i
>
=
x
j
x_i>=x_j
xi>=xj,那么条件(2),(3) 转化为
m
a
x
(
h
j
+
x
j
)
,
m
i
n
(
−
x
j
)
max(h_j+x_j),min(-x_j)
max(hj+xj),min(−xj)。
那么我们开两棵线段树,一棵线段树维护 m a x ( h j − x j ) , m i n ( x j ) max(h_j-x_j),min(x_j) max(hj−xj),min(xj),另一棵线段树维护 m a x ( h j + x j ) , m i n ( − x j ) max(h_j+x_j),min(-x_j) max(hj+xj),min(−xj)。
时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
namespace onlyzhao
{
#define ui unsigned int
#define ll long long
#define llu unsigned ll
#define ld long double
#define pr make_pair
#define pb push_back
#define lc (cnt<<1)
#define rc (cnt<<1|1)
#define len(x) (t[(x)].r-t[(x)].l+1)
#define tmid ((l+r)>>1)
#define fhead(x) for(int i=head[(x)];i;i=nt[i])
//#define max(x,y) ((x)>(y)?(x):(y))
//#define min(x,y) ((x)>(y)?(y):(x))
#define one(n) for(int i=1;i<=(n);i++)
#define rone(n) for(int i=(n);i>=1;i--)
#define fone(i,x,n) for(int i=(x);i<=(n);i++)
#define frone(i,n,x) for(int i=(n);i>=(x);i--)
#define fonk(i,x,n,k) for(int i=(x);i<=(n);i+=(k))
#define fronk(i,n,x,k) for(int i=(n);i>=(x);i-=(k))
#define two(n,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define ftwo(i,n,j,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
#define fvc(vc) for(int i=0;i<vc.size();i++)
#define frvc(vc) for(int i=vc.size()-1;i>=0;i--)
#define forvc(i,vc) for(int i=0;i<vc.size();i++)
#define forrvc(i,vc) for(int i=vc.size()-1;i>=0;i--)
#define cls(a) memset(a,0,sizeof(a))
#define cls1(a) memset(a,-1,sizeof(a))
#define clsmax(a) memset(a,0x3f,sizeof(a))
#define clsmin(a) memset(a,0x80,sizeof(a))
#define cln(a,num) memset(a,0,sizeof(a[0])*num)
#define cln1(a,num) memset(a,-1,sizeof(a[0])*num)
#define clnmax(a,num) memset(a,0x3f,sizeof(a[0])*num)
#define clnmin(a,num) memset(a,0x80,sizeof(a[0])*num)
#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define scl(x) scanf("%lld",&x)
#define scl2(x,y) scanf("%lld%lld",&x,&y)
#define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scf(x) scanf("%lf",&x)
#define scf2(x,y) scanf("%lf%lf",&x,&y)
#define scf3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scs(x) scanf("%s",x+1)
#define scs0(x) scanf("%s",x)
#define scline(x) scanf("%[^\n]%*c",x+1)
#define scline0(x) scanf("%[^\n]%*c",x)
#define pcc(x) putchar(x)
#define pc(x) printf("%d\n",x)
#define pc2(x,y) printf("%d %d\n",x,y)
#define pc3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pck(x) printf("%d ",x)
#define pcl(x) printf("%lld\n",x)
#define pcl2(x,y) printf("%lld %lld\n",x,y)
#define pcl3(x,y,z) printf("%lld %lld %d\n",x,y,z)
#define pclk(x) printf("%lld ",x)
#define pcf2(x) printf("%.2f\n",x)
#define pcf6(x) printf("%.6f\n",x)
#define pcf8(x) printf("%.8f\n",x)
#define pcs(x) printf("%s\n",x+1)
#define pcs0(x) printf("%s\n",x)
#define pcline(x) printf("%d**********\n",x)
#define casett int tt;sc(tt);int pp=0;while(tt--)
char buffer[100001],*S,*T;
inline char Get_Char()
{
if (S==T)
{
T=(S=buffer)+fread(buffer,1,100001,stdin);
if (S==T) return EOF;
}
return *S++;
}
inline int read()
{
char c;int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
return re;
}
};
using namespace onlyzhao;
using namespace std;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e9;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1.0);
const int hp=13331;
const int maxn=100100;
const int maxm=100100;
const int up=100100;
ll h[maxn],x[maxn];
int n,s;
struct node
{
int l,r;
ll maxx,minn;
int id;
};
void pushup(node &now,const node &l,const node &r)
{
if(l.maxx>r.maxx)
{
now.maxx=l.maxx;
now.minn=l.minn;
now.id=l.id;
}
else if(l.maxx<r.maxx)
{
now.maxx=r.maxx;
now.minn=r.minn;
now.id=r.id;
}
else
{
if(l.minn<r.minn)
{
now.maxx=l.maxx;
now.minn=l.minn;
now.id=l.id;
}
else if(l.minn>r.minn)
{
now.maxx=r.maxx;
now.minn=r.minn;
now.id=r.id;
}
else
{
if(l.id<r.id)
{
now.maxx=l.maxx;
now.minn=l.minn;
now.id=l.id;
}
else
{
now.maxx=r.maxx;
now.minn=r.minn;
now.id=r.id;
}
}
}
}
struct xds
{
node t[maxn<<2];
void build(int l,int r,int cnt)
{
t[cnt].l=l,t[cnt].r=r;
if(l==r)
{
t[cnt].maxx=h[l]-x[l];
t[cnt].minn=x[l];
t[cnt].id=l;
return ;
}
build(l,tmid,lc);
build(tmid+1,r,rc);
pushup(t[cnt],t[lc],t[rc]);
}
node ask(int l,int r,int cnt)
{
if(l<=t[cnt].l&&t[cnt].r<=r)
return t[cnt];
node now;
if(r<t[rc].l) now=ask(l,r,lc);
else if(l>t[lc].r) now=ask(l,r,rc);
else pushup(now,ask(l,r,lc),ask(l,r,rc));
return now;
}
void change(int pos,int cnt)
{
if(t[cnt].l==t[cnt].r)
{
t[cnt].maxx=-lnf;
t[cnt].minn=lnf;
t[cnt].id=-1;
return ;
}
if(pos<=t[lc].r) change(pos,lc);
else change(pos,rc);
pushup(t[cnt],t[lc],t[rc]);
}
}t1,t2;
set<ll>se;
map<ll,int>mp;
int main(void)
{
scanf("%d%d",&n,&s);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&x[i],&h[i]);
se.insert(x[i]);
mp[x[i]]=i;
}
t1.build(1,n,1);
for(int i=1;i<=n;i++)
x[i]=-x[i];
t2.build(1,n,1);
for(int i=1;i<=n;i++)
x[i]=-x[i];
t1.change(s,1);
t2.change(s,1);
se.erase(x[s]);
ll ans=0;
ll pos=x[s];
while(se.size())
{
auto now=se.upper_bound(pos);
node cc;
if(now==se.begin())
{
cc=t1.ask(1,n,1);
}
else if(now==se.end())
{
cc=t2.ask(1,n,1);
}
else
{
node xx=t2.ask(1,mp[*(--now)],1);
node yy=t1.ask(mp[*(++now)],n,1);
swap(xx,yy);
xx.maxx+=pos;
xx.minn-=pos;
yy.maxx-=pos;
yy.minn+=pos;
pushup(cc,xx,yy);
}
ans+=abs(x[cc.id]-pos);
t1.change(cc.id,1);
t2.change(cc.id,1);
se.erase(x[cc.id]);
pos=x[cc.id];
}
printf("%lld\n",ans);
return 0;
}