题意
给定仅由'+'和'-'组成的字符串
执行以下描述性代码
res = 0
for init = 0 to inf
cur = init
ok = true
for i = 1 to |s|
res = res + 1
if s[i] == '+'
cur = cur + 1
else
cur = cur - 1
if cur < 0
ok = false
break
if ok
break
问最后res的值为多少
限制
Time limit per test: 2 seconds
Memory limit per test: 256 megabytes
1≤t≤1000
1≤|s|≤106
Σ|s|≤106
解
代码块的含义为
init从0开始依次递增,cur每次初始值即为init
然后遍历字符串,遇 + 使 cur+1,遇 - 使 cur-1
如果cur在过程中出现了小于0的情况,则退出遍历,进入下一次循环
如果cur在整个过程中没有出现小于0的情况,则退出循环
这是一个折线图,且相邻两个位置高度相差必为1
从左往右遍历这张图,一旦遇到某个点小于0,说明这一遍将会停在这个位置并跳出遍历
所以这一遍res增加的数值即为这个位置的数值
其后让起始点增加1(也表明整张图上移一格)继续判断
所以可以定义变量mn和cur初始值为0,遍历字符串
遇 + 使 cur+1,遇 - 使 cur-1
如果遍历中出现cur<mn的情况,说明上述代码块在init == -mn时会在该位置出现cur<0而退出遍历的情况
所以此时答案要加上当前位置,并让mn=cur(或者mn-1),表明init自增后继续执行
遍历结束后,答案还需加上字符串长度,表明退出代码块前执行的最后一次循环遍历了整个字符串
完整程序
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char str[1000050];
void solve()
{
scanf("%s",str+1);
ll ans=0,mn=0,cur=0;
int i;
for(i=1;str[i]!=' ';i++)
{
if(str[i]=='+')
cur++;
else
{
cur--;
if(cur<mn)
{
ans+=i; //加上该位置
mn=cur;
}
}
}
ans+=i-1; //加上字符串长度
printf("%d
",ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
solve();
return 0;
}