题目链接:
https://www.acwing.com/problem/content/description/4220/
二分修改的区间长度(即修改成本),然后对每段长度为mid
的区间进行判断。
二分的性质:修改一个长度短的区间可以到达目的地,那么修改长度长的也一定可以到达,因为可以随意修改。那么必然存在一个长度边界ans
,满足
l
e
n
≥
a
n
s
len \geq ans
len≥ans的全部可以到达目的地,
l
e
n
<
a
n
s
len<ans
len<ans的不能到达目的地。
分别计算x
和y
方向变化量的前缀和dx[]
,dy[]
c h e c k ( ) check() check()函数:
- 变量解释:
xx
:除修改区间以外的x的变换量
yy
:除修改区间以外的y的变换量
t1
:x方向上需要多少到达目的地
t2
:y方向上需要多少到达目的地 - 对于每一个区间,求出除去修改区间以外的区间还需要多少
x
和y
方向上的变化量来到达目的地(x,y)。 - 对于
t1
,t2
, 首先需要满足 m i d > = a b s ( t 1 ) + a b s ( t 2 ) mid >= abs(t1)+abs(t2) mid>=abs(t1)+abs(t2) ,
其次如果有冗余的长度,即 m i d > a b s ( t 1 ) + a b s ( t 2 ) mid>abs(t1)+abs(t2) mid>abs(t1)+abs(t2) 的情况下,我们需要用两个相反的指令来抵消,
所以还需要满足 ( m i d − a b s ( t 1 ) − a b s ( t 2 ) ) % 2 = = 0 (mid-abs(t1)-abs(t2))\%2==0 (mid−abs(t1)−abs(t2))%2==0,另外答案为0和-1的时候先判断一下。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
char s[N];
int dx[N],dy[N];
int n,x,y;
bool check(int mid)
{
for(int i=1;i+mid-1<=n;i++)
{
int l = i,r = i+mid-1;
int xx = dx[n]-(dx[r]-dx[l-1]);//除修改区间以外的x的变换量
int yy = dy[n]-(dy[r]-dy[l-1]);//除修改区间以外的y的变化量
int t1 = x - xx;//x方向上需要多少到达目的地
int t2 = y - yy;//y方向上需要多少到达目的地
if(mid >= abs(t1) + abs(t2) && (mid-abs(t1)-abs(t2))%2==0) return true;
}
return false;
}
int main()
{
cin>>n>>s+1>>x>>y;
for(int i=1;i<=n;i++)
{
dx[i] = dx[i-1], dy[i] = dy[i-1];
if(s[i]=='R') dx[i] ++;
else if(s[i]=='L') dx[i] --;
if(s[i]=='U') dy[i] ++;
else if(s[i]=='D')dy[i] --;
}
if(dx[n]==x && dy[n]==y)
{
cout<<0<<endl;
return 0;
}
if(!check(n))
{
cout<<-1<<endl;
return 0;
}
int l = 0,r = n;
while(l<r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout<<l<<endl;
return 0;
}