给出了()的字符串,这里的()字符串可以看成是dfs序列,再求lca时的那张表。
所以这一个序列就可以看成是在dfs序上面,求树的直径。
取某一段[l,r],可以知道lca一定在[l,r]之间。
我们就用公式 diameter=hight[l]+height[r]-2* height[lca(l,r)]来维护两个点的之间的距离。
把(看成1,)看成-1,可以发现height[i]=sufix[i],即前缀和。
所以我们建立一颗线段树,维护hight[l]+height[r]-2* height[lca(l,r)]这个式子即可。
针对这个式子,我们一共有三种方式可以统计diameter,当前区间的diameter=max(左子树diameter,右子树diameter,跨接两个区间的diameter )
关在在于怎么去求跨界两个区间的。我们可以维护 height[l]-2*height[lca]来得到。即左子树的 往右边方向的lca去连接右边,右子树 往左边方向走的lca去链接左边,满足l<=lca<=r,即lca在我们取的两点之间。(注意合并时还有细节,比如我们并没有直接维护前缀和,而是根节点置为深度1,不断加深度来完成,方便后面更新节点,也可以直接维护深度进行区间修改,不过要复杂一点)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#define up(i,a,b) for(int i=a;i
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
struct node {
int depth, lmx, rmx, mn, mx,as;
node operator +(const node a)const {
node b;
b.depth = depth + a.depth;
b.mx = max(mx, a.mx + depth);
b.mn = min(mn, a.mn + depth);
b.lmx = max(lmx, a.lmx - depth); b.lmx = max(b.lmx, mx - 2 * a.mn - 2 * depth);
b.rmx = max(rmx, a.rmx - depth); b.rmx = max(b.rmx, a.mx - 2 * mn + depth);
b.as = max(as, a.as);
b.as = max(b.as, max(lmx + a.mx + depth, a.rmx + mx - depth));
return b;
}
}tree[N << 2];
void update(int l, int r, int root, int pos,int val)
{
if (l == r)
{
tree[root].depth = val;
tree[root].mn = tree[root].mx = val;
tree[root].lmx = tree[root].rmx = -val;
tree[root].as = 0;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)update(lson, pos, val);
else update(rson, pos, val);
tree[root] = tree[lrt] + tree[rrt];
}
int n, q;
int a, b;
char s[N];
int main()
{
n = read(); q = read();
n = 2 * n - 2;
cin >> s + 1;
upd(i, 1, n)
{
update(1, n, 1, i, s[i] == '(' ? 1 : -1);
}
printf("%d\n", tree[1].as);
while (q--)
{
a = read(), b = read();
update(1, n, 1, a, s[b] == '(' ? 1 : -1);
update(1, n, 1, b, s[a] == '(' ? 1 : -1);
swap(s[a], s[b]);
printf("%d\n", tree[1].as);
}
return 0;
}