codeforces 1149c

一世执手 提交于 2019-12-01 10:14:56

给出了()的字符串,这里的()字符串可以看成是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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!