GYM106191F-Bracket Sequences

GYM106191F-Bracket Sequences

题目大意

给你一串数字,正数表示连续的左括号,负数表示连续的右括号。题目要求有多少个子区间,满足任意重排这个子区间后能组成正确的括号串,并且相邻两个数中至少有一个为负数。

题解

不难发现要满足能组成正确的括号串,左括号减右括号要等于 \(0\)

难以发现的是,要满足第二个条件,负数必须大于等于正数的数量。

所以我们可以按条件一,将所有位置 \(poi\) 分类,同一类位置之间满足条件一。然后在其之间找满足条件二的区间数。

我们维护一个 \(cnt=sum_{负数}-sum_{正数}\) ,用树状数组维护前面有多少 \(cnt_i \le cnt_j\)

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define umap unordered_map
#define endl '\n'
using namespace std;
using i128 = __int128;
const int mod =1e9+7;
template <typename T>void read(T&x){
    x=0;int f = 1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    x*=f;
}
template <typename T>void print(T x) {
     if (x < 0) { putchar('-'); x = -x; }
     if (x > 9) print(x / 10);
     putchar(x % 10 + '0');
}
#define int long long
class FenwickTree {
private:
    vector<int> tree;  
    int n;  
    int lowbit(int x) {
        return x & -x;
    }

public:
    FenwickTree(int size=0) : n(size), tree(size + 1, 0) {}

    void add(int pos, int val) {
    	if(pos==0) 
    	{
    		tree[0]+=val;
    		return;
		}
        for (int i = pos; i <= n; i += lowbit(i)) {
            tree[i] += val;
        }
    }
    int query(int pos) {
        int sum = 0;
        for (int i = pos; i > 0; i -= lowbit(i)) {
            sum += tree[i];
        }
        return sum+tree[0];
    }
    int query(int left, int right) {
        return query(right) - query(left - 1);
    }
};
const int N=500005;
const int M=2000005;
inline void solve()
{
	int n;
	cin>>n;
	vector<int> num(n+1);
	for(int i=1;i<=n;i++) cin>>num[i];
	map<int,vector<int>> mp;
	vector<int> cnt(n+1);
	mp[0].push_back(0);
	int sum=0,sum1=0;
	for(int i=1;i<=n;i++)
	{
		sum1+=(num[i]>0?-1:1);
		sum+=num[i];
		mp[sum].push_back(sum1);
	} 
	int ans=0;
	map<long long, FenwickTree> fens;
	
	for (auto &[k, v]: mp) {
		fens[k] = FenwickTree(v.size()+5);
		sort(v.begin(), v.end());
	}
	
	sum=sum1=0;
	fens[sum].add(lower_bound(mp[sum].begin(), mp[sum].end(), sum1) - mp[sum].begin(), 1);
	for (int i = 1; i <= n; i ++) {
		sum += num[i];
		sum1+= (num[i]>0?-1:1);
		int p = lower_bound(mp[sum].begin(), mp[sum].end(), sum1) - mp[sum].begin();
		ans += fens[sum].query(p);
		fens[sum].add(p, 1);
	}
	cout<<ans<<endl;
	
}

signed main()
{
//	ios;
	int T=1;
//	cin>>T;
	for(;T--;) solve();
	return 0;
}
posted @ 2025-11-19 19:08  NDAKJin  阅读(5)  评论(0)    收藏  举报