codeforces 733E

题目大意

n 级台阶,每一级台阶有一个符号U或D。
假如你在第i级台阶,符号是U,那么你下一步会在 i+1 ,反之则在 i1 .
假如你在某个时刻离开了第 i 级台阶,那一位的标识符就会翻转,U变成D,D变成U。

问你从每一级台阶开始走,直到离开楼梯(可以下端或上端),需要多少时间?

解题思路

首先假如有cntu个U, cntd 个D,那么你从最上端的 cntu 级台阶开始走,一定最后从上方走出,反之则从下方走出。
证明:
假如在从上往下数第 x,xcntu 个,其包括其上方共有 y 个U.
你会发现一个事实,假如我最后要从上方走出,那么我这个位置上方(包括自己)的D的数量小于等于自己下方U的数量。

xycntuy

xcntu

得证。

然后呢?

假如某个位置上方有个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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值