首页 > 其他分享 >P3215 括号修复 题解

P3215 括号修复 题解

时间:2024-10-07 09:23:05浏览次数:11  
标签:ch int 题解 tot P3215 括号 ai Vi asi

Statement

维护一个括号序列,有以下操作:

  • 区间覆盖
  • 区间翻转
  • 区间反转(左括号变右括号,右括号变左括号)
  • 区间问最少改多少位能使括号序列合法,保证有解

Solution

单纯没想到答案怎么算。。。

首先一段括号序,如果消除中间的所有匹配,最终一定形如 ))))(((,这个信息是可合并的

设这时左括号数为 \(a\),右括号数为 \(b\),答案等于 \(\lceil\frac a2\rceil+\lceil\frac b2\rceil\)

对于区间翻转和区间反转,再维护一下翻转、反转后的 \(a\) 和 \(b\) 即可。

套上 FHQ 做完了。

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;
const int N = 1e5 + 10;
struct Item {
	int x, y;
	Item operator+ (const Item& rhs) const {
		return (Item){x + max(0, rhs.x - y), rhs.y + max(0, y - rhs.x)};
	}
} a[N], ai[N], as[N], asi[N], V[N], Vi[N];
int n, q, tot, rt, A, B, C, b[N], sz[N], co[N], sw[N], in[N], ch[N][2];
mt19937 rnd(251);
string s;

int New(char c) {
	sz[++tot] = 1, b[tot] = rnd(), co[tot] = 2;
	V[tot].x = Vi[tot].y = a[tot].x = ai[tot].y = as[tot].x = asi[tot].y = c == ')';
	V[tot].y = Vi[tot].x = a[tot].y = ai[tot].x = as[tot].y = asi[tot].x = !a[tot].x;
	return tot;
}
void up(int u) {
	sz[u] = sz[ch[u][0]] + 1 + sz[ch[u][1]];
	a[u] = a[ch[u][0]] + V[u] + a[ch[u][1]];
	ai[u] = ai[ch[u][0]] + Vi[u] + ai[ch[u][1]];
	as[u] = as[ch[u][1]] + V[u] + as[ch[u][0]];
	asi[u] = asi[ch[u][1]] + Vi[u] + asi[ch[u][0]];
}
void Cov(int u, int o) {
	co[u] = o, in[u] = 0;
	if (o) V[u].x = Vi[u].y = 1, a[u].x = ai[u].y = as[u].x = asi[u].y = sz[u], V[u].y = Vi[u].x = a[u].y = ai[u].x = as[u].y = asi[u].x = 0;
	else V[u].y = Vi[u].x = 1, a[u].y = ai[u].x = as[u].y = asi[u].x = sz[u], V[u].x = Vi[u].y = a[u].x = ai[u].y = as[u].x = asi[u].y = 0;
}
void Swp(int u) {
	swap(a[u], as[u]), swap(ai[u], asi[u]), swap(ch[u][0], ch[u][1]), sw[u] ^= 1;
}
void Inv(int u) {
	swap(a[u], ai[u]), swap(as[u], asi[u]), swap(V[u], Vi[u]), in[u] ^= 1;
}
void down(int u) {
	if (co[u] != 2) Cov(ch[u][0], co[u]), Cov(ch[u][1], co[u]), co[u] = 2;
	if (sw[u]) Swp(ch[u][0]), Swp(ch[u][1]), sw[u] = 0;
	if (in[u]) Inv(ch[u][0]), Inv(ch[u][1]), in[u] = 0;
}
void spl(int u, int k, int &x, int &y) {
	if (!u) return (void)(x = y = 0);
	down(u);
	if (k <= sz[ch[u][0]]) y = u, spl(ch[u][0], k, x, ch[u][0]);
	else x = u, spl(ch[u][1], k - sz[ch[u][0]] - 1, ch[u][1], y);
	up(u);
}
int mer(int u, int v) {
	if (!u || !v) return u | v;
	down(u), down(v);
	if (b[u] < b[v]) return ch[u][1] = mer(ch[u][1], v), up(u), u;
	else return ch[v][0] = mer(u, ch[v][0]), up(v), v;
}

int F(int x) {
	return x / 2 + (x % 2 == 1);
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	cin >> n >> q >> s;
	rep(i, 0, n - 1) rt = mer(rt, New(s[i]));
	while (q--) {
		string op;
		int l, r;
		char c;
		cin >> op >> l >> r;
		spl(rt, l - 1, A, B), spl(B, r - l + 1, B, C);
		if (op[0] == 'R') cin >> c, Cov(B, c == ')');
		if (op[0] == 'S') Swp(B);
		if (op[0] == 'I') Inv(B);
		if (op[0] == 'Q') cout << F(a[B].x) + F(a[B].y) << '\n';
		rt = mer(mer(A, B), C);
	}
	return 0;
}

标签:ch,int,题解,tot,P3215,括号,ai,Vi,asi
From: https://www.cnblogs.com/laijinyi/p/18449771

相关文章

  • P5416 = UOJ 198 时空旅行 题解
    Statement一棵树,每个节点上有一个集合,每个儿子集合由父亲集合增加一个点\((x_i,c_i)\)或删除一个点得到。根节点集合为\(\{(0,0,0,c_0)\}\)多次询问,每次问\(u\)点的集合内,\(\min\{(x_i-x)^2+c_i\}\)Solution首先你认真读完题发现原题中\(y,z\)都是没用的然后离线DFS......
  • 火星商店问题 题解
    Solution线段树套trie,秒了!\(O(n\log^2n)\)Code#include<bits/stdc++.h>usingnamespacestd;#definerep(i,j,k)for(inti=(j);i<=(k);++i)#definereo(i,j,k)for(inti=(j);i>=(k);--i)typedeflonglongll;constintN=1e5+......
  • Gym 100543G Virus synthesis 题解
    Solution首先只考虑回文串的答案;我们重点考虑的是偶回文串结论:对于偶回文串\(u\),从其最长的长度小于等于他的一半的回文后缀,或其父亲转移过来,一定是最优的证明:设\(u\)的一个回文子串为\(v\)(不是父亲),你要让\(v\tou\)的转移最优首先\(v\)不能跨过\(u\)的中点,因为此......
  • LOJ 6041 事情的相似度 题解
    Statement先把串reverse,多次给\(l,r\),求\[\max_{l\lei<j\ler}\{\text{LCP}(i,j)\}\]Solution\(\text{sqrtlog}\sim\text{sqrt}\):莫队+线段树/树状数组/set,用SA做\(nm/\omega\):bitset乱搞\(\log^2\):SAM+LCT+BIT在parent树上,LCP等于LCA的......
  • P3332 K大数查询 题解
    Solution整体二分板子题vector太好写了111#include<bits/stdc++.h>usingnamespacestd;#definerep(i,j,k)for(inti=(j);i<=(k);++i)#definereo(i,j,k)for(inti=(j);i>=(k);--i)typedeflonglongll;constintN=50010;intn,m,ans[......
  • P4093 序列 题解
    Statement给出\(n\) 个数的序列\(\{a_i\}\),接下来\(m\)秒中每一秒会有一个数发生变化,然后恢复。问最长的子序列长度,使得任意时刻这个子序列不下降。\(n\le10^5\)Solution设\(b_i\)为\(i\)最小能变成的数,\(c_i\)为\(i\)最大能变成的数\[f(i)=\max_{j<i\landc......
  • P4690 镜中的昆虫 (动态区间颜色数) 题解
    Statement区间涂颜色区间颜色数Solution\(O(\text{polysqrt})\)略。\(O(\text{polylog})\)颜色段均摊有两层含义:随机数据下:任意时刻的颜色段个数期望\(O(\logn)\)非随机数据下:每次推平时访问的颜色段个数均摊\(O(n)\)首先维护每个点\(i\)的\(pre_i\),一次询......
  • Codeforces Rund 977 div2 个人题解(A~E1)
    CodeforcesRund977div2个人题解(A,B,C1,C2,E1)Dashboard-CodeforcesRound977(Div.2,basedonCOMPFEST16-FinalRound)-Codeforces火车头#define_CRT_SECURE_NO_WARNINGS1#include<algorithm>#include<array>#include<bitset>#includ......
  • 【题解】C - STEP
    目录题目内容DescriptionInputOutput数据规模与约定做法一思路代码做法2思路代码题目内容原题:洛谷P6492Description给定一个长度为\(n\)的字符序列\(a\),初始时序列中全部都是字符L。有\(q\)次修改,每次给定一个\(x\),若\(a_x\)为L,则将\(a_x\)修改成R,否则将\(a_x\)......
  • 常见问题解决 --- maven手动安装依赖jar包报错
    报错内容:执行命令mvninstall:install-file-DgroupId=com.beidouapp-DartifactId=SSDK-Dversion=4.0.2.0 -Dfile=C:\1\SSDK-Release-4.0.2.0.jar-Dpackaging=jar报错Unknownlifecyclephase“.ggstar“.Youmustspecifyavalidlifecyclephaseoragoal原因:在pow......