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;
}

浙公网安备 33010602011771号