专栏文章
[P14610] [NWRRC 2025] Keys and Grates 题解
P14610题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mimzdgju
- 此快照首次捕获于
- 2025/12/01 18:02 3 个月前
- 此快照最后确认于
- 2025/12/01 18:02 3 个月前
实际上只需要模拟整个流程即可。
先尝试 ,可能会有阻碍,于是 ,其中 ,拿到通过 所有门的钥匙。然后尝试 ,可能会有阻碍,于是 ,其中 ,拿到通过 所有门的钥匙,以此类推。终止条件是,没有门在 路径上。
判定无解时,注意到 单增, 单减,若不满足这两个条件中任意一个,则说明存在一个钥匙落在了无法到达的位置。当然 时,如果有一个钥匙被其对应的门挡在了前面,也无解,具体可以前缀和找是否有 使得 ,或者是否有 使得 。
离散化 后使用 ST 表即可快速查 与 。时间复杂度 。
code
CPP#include<bits/stdc++.h>
#define pb emplace_back
#define pob pop_back
#define mp make_pair
using namespace std;
typedef long long ll;
const ll maxn=500007,ee=1e18,V=1e7;
ll n,m,S,T,a[maxn],b[maxn],c[maxn],su[maxn][2];
ll mx[maxn][20],mn[maxn][20],ans;
void ups(ll &a,ll b){a=min(a,b);}
ll QMN(ll l,ll r){
if(l>r) return ee;
ll k=__lg(r-l+1);
return min(mn[l][k],mn[r-(1<<k)+1][k]);
}
ll QMX(ll l,ll r){
if(l>r) return -ee;
ll k=__lg(r-l+1);
return max(mx[l][k],mx[r-(1<<k)+1][k]);
}
ll solve(ll l,ll r,bool typ){
if(l>r) return 0;
if(typ==0){
if(su[r][0]-su[S-1][0]) return -1;
ll mn=QMN(S,r);
if(l>=mn) return -1;
if(mn>=S) return 0;
ll res=solve(mn,r,1);
if(res==-1) return -1;
return res+2*(c[S]-c[mn]);
}else{
if(su[S][1]-su[l-1][1]) return -1;
ll mx=QMX(l,S);
if(r<=mx) return -1;
if(mx<=S) return 0;
ll res=solve(l,mx,0);
if(res==-1) return -1;
return res+2*(c[mx]-c[S]);
}
}
ll solve(void){
m=2*n+2;
for(ll i=1;i<=n;i++) c[2*i-1]=a[i],c[2*i]=b[i];
c[2*n+1]=S,c[2*n+2]=T;
sort(c+1,c+1+m);
for(ll i=1;i<=n;i++){
a[i]=lower_bound(c+1,c+1+m,a[i])-c;
b[i]=lower_bound(c+1,c+1+m,b[i])-c;
}
S=lower_bound(c+1,c+1+m,S)-c;
T=lower_bound(c+1,c+1+m,T)-c;
if(S>T){
S=m-S+1,T=m-T+1;
for(ll i=1;i<=n;i++) a[i]=m-a[i]+1,b[i]=m-b[i]+1;
for(ll i=1;i<=m;i++) c[i]=V-c[i];
reverse(c+1,c+1+m);
}
for(ll i=1;i<=m;i++){
mn[i][0]=ee,mx[i][0]=-ee;
su[i][0]=su[i][1]=0;
}
for(ll i=1;i<=n;i++){
mn[b[i]][0]=mx[b[i]][0]=a[i];
if(a[i]>b[i]) su[b[i]][0]++;
else su[b[i]][1]++;
}
for(ll i=1;i<=m;i++) su[i][0]+=su[i-1][0],su[i][1]+=su[i-1][1];
for(ll j=1;j<=19;j++){
for(ll i=1;i+(1<<j)-1<=m;i++){
mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
}
}
ans=solve(0,T,0);
if(ans==-1) return -1;
return ans+c[T]-c[S];
}
int main(void){
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0);
ll Tc=1; cin>>Tc;
for(;Tc--;){
cin>>n>>S>>T;
for(ll i=1;i<=n;i++) cin>>a[i]>>b[i];
cout<<solve()<<"\n";
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...