[CF1473D] Program - 线段树
Description
有一个变量 x 初始为 0,我们按字符串顺序进行“+1”或“-1”操作。有 m 个询问,每次询问我们删去字符串的 l 到 r 的符号后,x 在完成所有操作中出现的不同数值的总数。
Solution
线段树每个结点维护 sum 表示这一段的操作和,maxsum 表示执行这一段操作过程中到达的最大值,minsum 表示执行这一段操作过程中到达的最小值。
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct SegmentTree
{
struct Node
{
int sum;
int min_sum;
int max_sum;
Node()
{
sum = 0;
min_sum = 0;
max_sum = 0;
}
Node(int sum, int min_sum, int max_sum) : sum(sum), min_sum(min_sum), max_sum(max_sum)
{
}
Node operator+(const Node &rhs)
{
return {sum + rhs.sum,
min(0ll, min(min_sum, sum + rhs.min_sum)),
max(0ll, max(max_sum, sum + rhs.max_sum))};
}
};
vector<Node> node;
int n;
SegmentTree(int n) : n(n)
{
node.resize(n * 4 + 2);
}
void build(int p, int l, int r, const string &str)
{
if (l == r)
node[p] = {str[l - 1] == '+' ? 1 : -1,
str[l - 1] == '+' ? 1 : -1,
str[l - 1] == '+' ? 1 : -1};
else
{
build(p * 2, l, (l + r) / 2, str);
build(p * 2 + 1, (l + r) / 2 + 1, r, str);
node[p] = node[p * 2] + node[p * 2 + 1];
}
}
void Build(const string &str)
{
build(1, 1, n, str);
}
Node query(int p, int l, int r, int ql, int qr)
{
if (l > qr || r < ql)
return {0, 0, 0};
if (l >= ql && r <= qr)
return node[p];
return query(p * 2, l, (l + r) / 2, ql, qr) + query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
}
Node Query(int ql, int qr)
{
return query(1, 1, n, ql, qr);
}
int Solve(int l, int r)
{
if (l == 1 && r == n)
return 1;
Node t = Query(1, l - 1) + Query(r + 1, n);
// cout << "solve " << t.sum << " " << t.max_sum << " " << t.min_sum << endl;
return t.max_sum - t.min_sum + 1;
}
};
void solve()
{
int n, m;
cin >> n >> m;
string str;
cin >> str;
SegmentTree seg(n);
seg.Build(str);
for (int i = 1; i <= m; i++)
{
int l, r;
cin >> l >> r;
cout << seg.Solve(l, r) << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
{
solve();
}
}