http://codeforces.com/contest/404/problem/E
Valera has a strip infinite in both directions and consisting of cells. The cells are numbered by integers. The cell number 0 has a robot.
The robot has instructions — the sequence of moves that he must perform. In one move, the robot moves one cell to the left or one cell to the right, according to instructions. Before the robot starts moving, Valera puts obstacles in some cells of the strip, excluding cell number 0. If the robot should go into the cell with an obstacle according the instructions, it will skip this move.
Also Valera indicates the finish cell in which the robot has to be after completing the entire instructions. The finishing cell should be different from the starting one. It is believed that the robot completed the instructions successfully, if during the process of moving he visited the finish cell exactly once — at its last move. Moreover, the latter move cannot be skipped.
Let's assume that k is the minimum number of obstacles that Valera must put to make the robot able to complete the entire sequence of instructions successfully and end up in some finishing cell. You need to calculate in how many ways Valera can choose k obstacles and the finishing cell so that the robot is able to complete the instructions successfully.
Input
The first line contains a sequence of characters without spaces s1s2... sn (1 ≤ n ≤ 106), consisting only of letters "L" and "R". If character si equals "L", then the robot on the i-th move must try to move one cell to the left. If the si-th character equals "R", then the robot on the i-th move must try to move one cell to the right.
Output
Print a single integer — the required number of ways. It's guaranteed that this number fits into 64-bit signed integer type.
题意:一个机器人在数轴上的0点 给一串指令机器人按照指令走 为了使机器人最后一步走到一个从来没来过的位置 我们可以在数轴上放石头 每次机器人被石头卡住他就跳过当前的那个指令 问 最少使用石头前提下 一共几种放石头方法
思路:
1.最后一个指令是L/R,一定停在0的左/右侧。因为最后一个命令是L,即向左走走到了新位置,这时一定是在0的左侧,因为如果在右侧,从0到这个位置是都走过的;如果最后一个命令是R,即向右走走到了新位置,这时一定是在0的右侧。
2.要么不放障碍,要么只放一个。(以下均以最后一个指令是R举例,L是对称的)既然最后在0右侧,那么放障碍一定不放在0的右侧,否则要么没用,要么阻碍完成目标,因此只放左边,放多个和放一个是一样的,只取决于最靠右的那个。
3.不放障碍就可以的话就输出1结束,放1个障碍不管放在哪都不行的话,那就确实是不行的。主要考虑放一个障碍的情形。
4.二分性质:放在x处可行的话,那么放在[x+1,-1]也是可行的。拿x+1举例,我们想象这个执行的过程,a和b都到了x+1,然后向左一个,a到了x,b还是在x+1,之后b的每一个动作就相当于a右移一格的。
做法:二分放障碍的最远位置,往外都不行,往内都行,输出个数。
#include<bits/stdc++.h>
using namespace std;
#define base 1000000
#define maxn 2000000+100
char s[maxn];
int v[maxn];
int n,ans;
bool check(int p)
{
int pos=0;
memset(v,0,sizeof(v));
v[pos+base]=1;
for(int i=1;i<=n;i++)
{
if(s[i]=='L'&&p==pos-1 || s[i]=='R'&&p==pos+1)continue;
s[i]=='L'?pos--:pos++;
v[base+pos]++;
}
return v[base+pos]==1;
}
int main()
{
//freopen("input.in","r",stdin);
scanf("%s",s+1);
n=strlen(s+1);
if(check(base*10)){cout<<1;exit(0);}
int l,r,m;
if(s[n]=='L')l=1,r=n;
else l=-n,r=-1;
while(l<=r)
{
m=(l+r)/2;
if(check(m))s[n]=='L'?l=m+1:r=m-1,ans=m;
else s[n]=='L'?r=m-1:l=m+1;
}
cout<<abs(ans);
return 0;
}