codeforces 733E

来源:互联网 发布:软件项目测试报告 编辑:程序博客网 时间:2024/05/16 07:48

题目大意

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 longusing 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
原创粉丝点击