Loading

题解:CF1976D Invertible Bracket Sequences

可以在 cnblog 中阅读。

题意

给一个合法括号序列,问有多少区间 \([l,r]\),使得将区间内的每个括号翻转后,括号序列仍合法。

分析

十分套路地,我们将 ( 看成 \(+1\),将 ) 看成 \(-1\),则一个括号序列合法的充要条件是转换后的序列满足:

  1. 前缀和任意位置非负;
  2. 最后一项为 \(0\)

考虑翻转括号序列意味着什么。翻转后 \(+1,-1\) 对调,为保证条件二,需要满足区间内的 \(+1,-1\) 数量相等,条件一则可以通过前缀和折线图来思考。

反转后,折线图的向上变为向下,向下变为向上,实际上就是上下对称地翻转过来,对称轴就是区间的左右端点较小值。不合法当且仅当折下去低于 x 轴。

这样条件就明朗了,我们可以将前缀和丢进 map 里面,在右端点处统计对答案的贡献。最后再把折下去不合法的从 map 里扔出去。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)

void solve()
{
	string s; cin>>s;
	map<int,int> cnt;
	cnt[0]=1;
	int st=0,ans=0;
	for(char c:s)
	{
		if(c=='(') st++;
		else st--;
		ans+=cnt[st];
		cnt[st]++;
		while((*cnt.begin()).first*2<st) cnt.erase(cnt.begin());
	}
	cout<<ans<<endl;
}

signed main()
{
	IOS;
	int T; cin>>T;
	while(T--) solve();
	return 0;
}
posted @ 2024-10-03 10:06  tai_chi  阅读(23)  评论(0编辑  收藏  举报