拙者

题目描述

我们定义一个括号序列是高兴的,当且仅当它右括号的个数不超过左括号的个数。

现在你要维护一个长度为 $n$ 的括号序列,编号为 $1−n$ ,支持以下三种操作:

1 $p$ 表示将第 $p$ 个括号反向,既 $($ 变为 $)$ , $)$ 变为 $($ 。

2 $l$ $r$ 表示询问:如果要使第 $l$ 个括号到第 $r$ 个括号组成的序列的每个前缀都是高兴的,至少需要删去多少个位置上的括号。

3 $l$ $r$ 表示询问:如果要使第 $l$ 个括号到第 $r$ 个括号组成的序列的每个前缀和每个后缀都是高兴的,至少需要删去多少个位置上的括号。

数据范围

$n le 2 imes 10^5,q le 3 imes 10^5$

题解

考虑将 $[l,r]$ 的括号序列拉出,做个前缀和,然后表示成一个函数图象

如果是2操作的话,显然是 $max(-min,0)$

对于3操作,考虑贪心,将前缀先弄成合法,此时图象会发生偏移,每个点 $i$ 最终变为 $x_i-min(x_j
)(j<i)$

要使得后缀变得合法,则右端点要成为图象的最高点,因此要使前缀合法后的max降至右端点后才合法

因此用线段树维护极差即可

代码

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,a[N],q;char ch;
struct T{int in,ax,s,df;}t[N<<2],V;
#define Ls k<<1
#define Rs k<<1|1
#define mid ((l+r)>>1)
T hb(T x,T y){
    V.in=min(x.in,y.in+x.s);
    V.ax=max(x.ax,y.ax+x.s);
    V.df=max(max(x.df,y.df),y.ax+x.s-x.in);
    V.s=x.s+y.s; return V;
}
void build(int k,int l,int r){
    if (l==r){
        if (~a[l]) t[k]=(T){0,1,1,1};
        else t[k]=(T){-1,0,-1,0};
        return;
    }
    build(Ls,l,mid);build(Rs,mid+1,r);
    t[k]=hb(t[Ls],t[Rs]);
}
void upd(int k,int l,int r,int x){
    if (l==r){
        if (~a[l]) t[k]=(T){0,1,1,1};
        else t[k]=(T){-1,0,-1,0};
        return;
    }
    if (mid>=x) upd(Ls,l,mid,x);
    else upd(Rs,mid+1,r,x);
    t[k]=hb(t[Ls],t[Rs]);
}
T qry(int k,int l,int r,int L,int R){
    if (L<=l && r<=R) return t[k];
    if (mid>=R) return qry(Ls,l,mid,L,R);
    if (mid<L) return qry(Rs,mid+1,r,L,R);
    return hb(qry(Ls,l,mid,L,R),qry(Rs,mid+1,r,L,R));
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf(" %c",&ch),
        a[i]=((ch=='(')?1:-1);
    build(1,1,n);scanf("%d",&q);
    for (int op,x,y;q--;){
        scanf("%d%d",&op,&x);
        if (op<2) a[x]=-a[x],upd(1,1,n,x);
        else if (op<3){
            scanf("%d",&y);
            T v=qry(1,1,n,x,y);
            printf("%d
",max(0,-v.in));
        }
        else{
            scanf("%d",&y);
            T v=qry(1,1,n,x,y);
            printf("%d
",max(0,-v.in)+v.df-(v.s-v.in));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xjqxjq/p/11766818.html