题意
松鼠bored在看小马,现在他要逃避掉下来的石头,石头总是落在bored所在的区间的中间。他有两种选择,一种是向左'l',使区间右端点变为原来的区间中间,一种是向右'r',使区间左端点变为原来的区间中间。bored已经想好了自己的行动路线,为了让他可以继续看小马,请你告诉他下落石头从左到右的编号。
Solution
我们考虑,当石头下落到区间的中间时,松鼠如果向左移动,那么石头就在现在区间的右端点,接下来不管怎么移动,剩下的石头都会在这个石头的左边。松鼠如果向右移动,那么石头就这现在区间的左端点,因为松鼠只能在这个石头的右面移动,所以剩下的石头都在这个石头的右边,可以直接输出。
然后想一下向左移动时的石头咋办,发现向左时掉落的石头,掉的越早,位置越往后即输出的时间越晚,所以我们可以拿 (dfs) 模拟过程,或者拿栈存储向左掉落的石头,或者拿双端队列存储所有石头。
代码
栈
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char a[N];
int main(){
scanf("%s",a+1);
int len=strlen(a+1);
stack<int> rk;
for(int i=1;i<=len;i++){
if(a[i]=='l') rk.push(i);
else printf("%d
",i);
}
while(!rk.empty()){
printf("%d
",rk.top());
rk.pop();
}
return 0;
}
dfs
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char a[N];
int n;
void dfs(int st){
if(st==n) return ;
if(a[st]=='l'){
dfs(st+1);printf("%d
",st+1);
}
if(a[st]=='r'){
printf("%d
",st+1);dfs(st+1);
}
}
int main(){
while(scanf("%s",a)!=EOF){
n=strlen(a);
dfs(0);
}
return 0;
}
双端对列
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int dq[N];
char a[N];
int main(){
scanf("%s",a+1);
int len=strlen(a+1);
int st=1,ed=len;
for(int i=1;i<=len;i++){
if(a[i]=='l'){
dq[st]=i;
st++;
}
if(a[i]=='r'){
dq[ed]=i;
ed--;
}
}
for(int i=len;i>=1;i--)
printf("%d
",dq[i]);
}