Codeforces1556C Compressed Bracket Sequence (思维) (好题)

题目链接: Compressed Bracket Sequence

大致题意

给定一个数字序列 a a a, 奇数位置表示有多少个左括号, 偶数位置表示有多少个右括号.

现在问有多少个连续的子段, 满足子段中的括号可以正确匹配.

解题思路

思维 (感觉这个题好难啊, 可能是我不配打ACM, 555)

我们不妨枚举 l l l, 统计以当前 l l l处的左括号为起始的合法序列数量. 这样我们可以保证答案是不重不漏的.

此时产生的贡献有两种情况: ① l l l位置的左括号与后续右括号成功匹配时的贡献. ② l l l位置开始的合法子序列与后续合法子序列拼合产生的贡献.

例如: a [ ] = { 4 , 2 , 1 , 2 } a[] = \{ 4, 2, 1, 2 \} a[]={4,2,1,2} 括号序列为: (((( )) ( ))

我们现在位于位置1处. 此时:
(((( )) ( )) 红色部分产生①类型的贡献, 贡献度为2.

(((( )) ( ) ) 红色蓝色部分产生②类型的贡献, 贡献度为1.

(((( )) ( ) ) 绿色部分产生①类型的贡献, 贡献度为1.

你可能想说, 蓝色括号部分本身也会产生①类型的贡献, 但是此时我们只枚举到 1 1 1位置, 如果此时我们去计算 3 3 3位置的答案, 不符合我们的分类标准, 从而会导致答案重复计算.


我们来分析一下什么时候需要统计这两种类型的贡献:

对于①类型: 只有当用到当前 l l l位置的左括号时, 才会产生贡献. 我们在向后扫描的过程中, 会产生非 l l l位置的左括号, 这些左括号会优先与后续右括号进行匹配, 注意这些匹配并不会在 l l l处产生①类型贡献. 如上例中的蓝色部分.

对于②类型: 产生这部分贡献, 当且仅当不存在非 l l l位置且未匹配的左括号. 此时假设在 p o s pos pos位置满足条件, 表明区间 [ l , p o s − 1 ] [l, pos - 1] [l,pos1] [ l , p o s + 1 ] [l, pos + 1] [l,pos+1]都是合法的. 但是我们其实并没有记录 [ l , p o s + 1 ] [l, pos + 1] [l,pos+1]的情况, 因此会产生1的贡献.

AC代码

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E3 + 10;
int a[N];
int main()
{
    int n; cin >> n;
    rep(i, n) scanf("%d", &a[i]);

    ll res = 0;
    for (int l = 1; l <= n; l += 2) { 
		res += min(a[l], a[l + 1]); 
		int left = a[l] - a[l + 1];//left表示当前l位置剩余的, 未匹配的左括号数量.
        ll more = 0; // 表示非l位置, 剩余的未匹配的左括号数量, 如果为负数, 表明有 -more个右括号没有匹配.
    	for (int r = l + 3; r <= n; r += 2) {
    		if (left < 0) break; //如果l位置的左括号不够了, 则退出. 注意是严格小于0, 否则会少②类型贡献.

    		more += a[r - 1] - a[r];
    		if (more < 0) res += min<ll>(-more, left), left += more, more = 0;

    		if (!more) res++;
    	}
    }

    cout << res << endl;

    return 0;
}

END

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值