题目大意
有
n
级台阶,每一级台阶有一个符号U或D。
假如你在第
假如你在某个时刻离开了第
i
级台阶,那一位的标识符就会翻转,U变成D,D变成U。
问你从每一级台阶开始走,直到离开楼梯(可以下端或上端),需要多少时间?
解题思路
首先假如有
证明:
假如在从上往下数第
x,x≤cntu
个,其包括其上方共有
y
个U.
你会发现一个事实,假如我最后要从上方走出,那么我这个位置上方(包括自己)的D的数量小于等于自己下方U的数量。
即
x≤cntu
得证。
然后呢?
假如某个位置上方有个D,但是他要从上方离开,会出现什么情况。
假如序列是这样的:
UUDDUDUDU
我要从第5格出发。
8个时刻过后
UDDDUUUDU
而且回到了第5格。
看看交换了什么,从上往下第4格以及从上往下第4个U。
8个时刻意味着什么?
从上往下第4格以及从上往下第4个U位置差*2。
因为每个位置都经过了两边,所以,只有两个位置交换符号,其他不变。
接着就一直交换,直到这个位置往上都是U。
答案就是,交换的代价+最后全U往上的代价。
D同理。
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 1000005
#define ll long long
using namespace std;
int n;
char s[maxn];
int a[maxn];
ll ans[maxn];
int main(){
scanf("%d",&n);
fo(i,1,n) {
char c=getchar();
while (c!='U' && c!='D') c=getchar();
s[i]=c;
}
a[0]=0;
fo(i,1,n) if (s[i]=='D') a[++a[0]]=i;
ll tot=0;
fo(i,1,a[0]) {
tot+=(a[i]-i) * 2;
ans[i]=i+tot;
}
a[0]=0;
fd(i,n,1) if (s[i]=='U') a[++a[0]]=i;
tot=0;
fo(i,1,a[0]) {
int w=n-i+1;
tot+=(w-a[i]) * 2;
ans[w]=i+tot;
}
fo(i,1,n) printf("%lld ",ans[i]);
return 0;
}