CF1149C Tree Generator™
CF1149C Tree Generator™
不能暴力建树,考虑从括号序入手。
联想树上莫队的点括号序列,一段区间去掉匹配括号剩下的括号对应的点即为路径上的点,有特殊情况。
则这里边括号序列,发现特殊情况都给你省掉了,那么一条路径对应一个区间去掉匹配括号。
那么有,树上直径长度为任意区间去掉匹配括号后的长度的最大值。
考虑如何代数去除匹配括号,树上莫队是判奇偶,这里可以设左端点为 ,右端点为 。
问题变为找到相邻的两段,使后一段的数字和减前一段的数字和的差最大,这个差就是答案。
因为后一段的数字和,对应一条向下的链,前一段的数字和对应一条向上的链,减去是因为向上的链的非匹配括号数计算是反过来的,即 交换。
区间最大差,考虑维护区间前后缀最大差以及整个区间的最大差。
需要维护区间前后缀最大最小子段和辅助计算。
一棵线段树即可,时间复杂度 。
#include<bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')
inline int read()
{
int o = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
o = o * 10 + c - '0', c = getchar();
return o * f;
}
inline void write(int o)
{
if(o < 0)
{
putchar('-');
o = -o;
}
if(o > 9)
write(o / 10);
putchar(o % 10 + '0');
}
const int _ = 2e5 + 10;
int n, q;
int tr[_ << 2], su[_ << 2], lm[_ << 2], rm[_ << 2], ln[_ << 2], rn[_ << 2], ld[_ << 2], rd[_ << 2], zd[_ << 2];
// m 大 n 小 d 右减左
char s[_];
void pushup(int o)
{
su[o] = su[o << 1] + su[o << 1 | 1];
lm[o] = max(lm[o << 1], su[o << 1] + lm[o << 1 | 1]);
rm[o] = max(rm[o << 1 | 1], su[o << 1 | 1] + rm[o << 1]);
ln[o] = min(ln[o << 1], su[o << 1] + ln[o << 1 | 1]);
rn[o] = min(rn[o << 1 | 1], su[o << 1 | 1] + rn[o << 1]);
ld[o] = max(ld[o << 1], max(ld[o << 1 | 1] - su[o << 1], zd[o << 1] + lm[o << 1 | 1]));
rd[o] = max(rd[o << 1 | 1], max(su[o << 1 | 1] + rd[o << 1], zd[o << 1 | 1] - rn[o << 1]));
zd[o] = max(zd[o << 1] + su[o << 1 | 1], zd[o << 1 | 1] - su[o << 1]);
tr[o] = max(max(ld[o << 1 | 1] - rn[o << 1], rd[o << 1] + lm[o << 1 | 1]), max(tr[o << 1], tr[o << 1 | 1]));
}
void build(int o, int l, int r)
{
if(l == r)
{
int v = s[l] == '(' ? 1 : -1;
su[o] = v;
lm[o] = rm[o] = max(v, 0);
ln[o] = rn[o] = min(v, 0);
ld[o] = rd[o] = zd[o] = tr[o] = 1;
return;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
pushup(o);
}
void upd(int o, int l, int r, int p, int v)
{
if(l == r)
{
su[o] = v;
lm[o] = rm[o] = max(v, 0);
ln[o] = rn[o] = min(v, 0);
ld[o] = rd[o] = zd[o] = tr[o] = 1;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) upd(o << 1, l, mid, p, v);
else upd(o << 1 | 1, mid + 1, r, p, v);
pushup(o);
}
signed main()
{
n = read(), q = read();
scanf("%s", s + 1);
n = (n - 1) << 1;
build(1, 1, n);
write(tr[1]), he;
int a, b;
while(q--)
{
a = read(), b = read();
if(s[a] != s[b])
{
swap(s[a], s[b]);
upd(1, 1, n, a, s[a] == '(' ? 1 : -1);
upd(1, 1, n, b, s[b] == '(' ? 1 : -1);
}
write(tr[1]), he;
}
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121972
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话