给出了()的字符串,这里的()字符串可以看成是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<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<climits> #include<stack> #include<vector> #include<queue> #include<set> #include<map> //#include<regex> #include<cstdio> #define up(i,a,b) for(int i=a;i<b;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; }