• 拙者


    题目描述

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

    现在你要维护一个长度为 $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;
    }
  • 相关阅读:
    hdu 4309(最大流+枚举状态)
    hdu 1565+hdu 1569(最大点权独立集)
    hdu 3657(最大点权独立集)
    hdu 3491(最小割+拆点)
    hdu 4394(bfs)
    An Introduction to Numerical Analysis Example 6.1
    陶哲轩谈数学家的合作(来自陶哲轩在数学家Gowers的博文“Is massively collaborative mathematics possible?”上的评论)
    拉格朗日插值多项式之间的递推关系
    三角形的余弦定理
    三角形的余弦定理
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11766818.html
Copyright © 2020-2023  润新知