><
直接写中文了
Problem Statement
给定的是长度为N-1的字符串S. S中的每个字符都是<或>。
当对所有i(1≤i≤N-1)都满足以下条件时,N个非负整数a1,a2,[cdots],aN的序列被认为是满足的
- 如果Si = <:ai <ai + 1
- 如果Si =>:ai> ai + 1
找出N个非负整数的良好序列的元素的最小可能和。
约束条件
- 2≤N≤5×105
- S是长度为N-1的字符串,由<和>组成
Input
输入来自标准输入,格式如下:
S
Output
找出N个非负整数的良好序列的元素的最小可能和。
Sample Input 1
<>>
Sample Output 1
3
a =(0,2,1,0)是一个好序列,其总和为3。没有一个好序列,其总和小于3
Sample Input 2
<>>><<><<<<<>>><
Sample Output 2
28
题目链接:
https://vjudge.net/problem/AtCoder-5659
不难发现找到"<>"这个即可
"<>"左右两边的个数设为l,r;大的一个为maxn,小的一个为minn ,则两边的和为(maxn+1)/2*maxn+(minn+1)/2*minn-minn
"><"左右两边的个数设为l,r;两边的和为(l+1)/2*l+(r+1)/2*r
所以只要遍历一遍s即可,碰到"<>"另外讨论,其他情况假设有n个"<"或者">",则ans+=(n+1)/2*n;
AC代码
#include <bits/stdc++.h> #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x, y) memset(x, y, sizeof(x)) #define Maxn 1000000000000 + 10 using namespace std; string s; ll len; ll ans; void solve(ll start, ll sum, ll flag) //搜索起始位置,上一次共有sum个连续的<或者>,上一次有没有出现<> { ll i; ll f = 0; ll cnt = 1; //计数 char r = s[start]; for (i = start + 1; i < len; i++) { if (s[i] == r) cnt++; else { if (r == '<' && s[i] == '>') //存在<>,f=1 f = 1; break; } } if (flag == 1) { if (cnt > sum) { if (cnt > 1) { ans += (cnt + 1) * cnt / 2; ans -= sum; } else { ans += 1; ans -= sum; } } else { if (cnt > 1) { ans += (cnt + 1) * cnt / 2; ans -= cnt; } else { ans += 1; ans -= cnt; } } if (i >= len)//遍历完成 return; return solve(i, cnt, f); } else { if (cnt > 1) ans += (cnt + 1) * cnt / 2; else { ans += 1; } if (i >= len)//遍历完成 return; return solve(i, cnt, f); } } int main() { ans = 0; cin >> s; len = s.size(); solve(0, 0, 0); cout << ans << endl; }