CF380C Sereja and Brackets 括号序列+线段树

你可以手画一下,然后发现求的其实就是 $[l,r]$ 区间内合法序列匹配个数.

用线段树维护一下括号序列就可以了.

code:

#include <bits/stdc++.h>
#define N 1000005
#define ll long long
#define lson now<<1
#define rson now<<1|1
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
struct node {
    int sum,ans,mi,ma;
    node() { sum=ans=mi=ma=0; }
    node operator+(const node &b) const
    {
        node c;
        c.sum=sum+b.sum;
        c.ans=ans+b.ans+min(ma,-b.mi);
        c.mi=min(mi,sum+b.mi);
        c.ma=max(b.ma,ma+b.sum);
        return c;
    }
}s[N<<2];
char str[N];
void build(int l,int r,int now)
{
    if(l==r)
    {
        if(str[l]==‘(‘)
            s[now].sum=1,s[now].ma=1;
        else
            s[now].sum=-1,s[now].mi=-1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson),build(mid+1,r,rson);
    s[now]=s[lson]+s[rson];
}
node query(int l,int r,int now,int L,int R)
{
    if(l>=L&&r<=R)
        return s[now];
    int mid=(l+r)>>1;
    if(L<=mid&&R>mid)
        return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
    else if(L<=mid)
        return query(l,mid,lson,L,R);
    else
        return query(mid+1,r,rson,L,R);
}
int main()
{
    // setIO("input");
    int i,j,n,Q;
    scanf("%s%d",str+1,&Q);
    n=strlen(str+1),build(1,n,1);
    for(i=1;i<=Q;++i)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",query(1,n,1,l,r).ans<<1);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12386390.html

时间: 2024-11-11 22:15:59

CF380C Sereja and Brackets 括号序列+线段树的相关文章

BZOJ 4034 树上操作(树的欧拉序列+线段树)

刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 注意到操作3,询问x到根的路径之间点权和,容易发现这就是欧拉序列中的前缀和. 所以按照树的欧拉序列建线段树,然后操作1就变成单点修改,操作2,就变成了区间内某些点+a,某些点-a,也容易用tag标记

hdu45221——小明系列问题——小明序列 线段树优化dp

小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1918    Accepted Submission(s): 583 Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找

BZOJ 1798 AHOI2009 Seq 维护序列 线段树

题目大意:维护一个序列,提供三种操作: 1.将区间中每个点的权值乘上一个数 2.将区间中每个点的权值加上一个数 3.求一段区间的和对p取模的值 2631的超^n级弱化版.写2631之前能够拿这个练练手... 线段树区间改动,让学校的大神指导了一下ZKW的区间改动方法,非常好理解,可是代码还是快不了. . . 回头再改改代码吧 可能是我写的太渣了 #include<cstdio> #include<cstring> #include<iostream> #include&

hdu 4521 小明系列问题——小明序列 线段树+二分

小明系列问题——小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,可是也就因为这样,小明几乎已经玩遍各种序列问题了.可怜的小明苦苦地在各大网站上寻找着新的序列问题,可是找来找去都是自己早已研究过的序列.小明想既然找不到,那就自己来发明一个新的序列问题吧!小明想啊想,终于想出了一个新的序列

【BZOJ4540】【Hnoi2016】序列 线段树

Claris劲啊!CA劲啊! %%%两位线段树做法传送门在这里和这里 逆向题解时间到: 首先将询问按照终点排序,并且一边从到遍历,不妨设当前遍历到了点,对于之前的每个点,我们维护两个值和.(之后的点的两个值都先设成0) 其中表示从这个点到之间序列A的最小值,而,表示从我们遍历第一个点到当前的所有时刻下的各个历史版本的和.(当遍历的点在这个点之前等于零)(事实上.) 不(很)难发现对于每一个询问,当且仅当时,有.因为 也就是说,如果我们把询问全部离线下来,遍历的时候可以快速更新并且求和,,我们就可

hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)

小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1553    Accepted Submission(s): 457 Problem Description 大家都知道小明最喜欢研究跟序列有关的问题了,但是也就由于这样,小明差点儿已经玩遍各种序列问题了.可怜的小明苦苦地在各大站点上寻找着新的序列问题,但是找来

poj 2828 Buy Tickets 【买票插队找位置 输出最后的位置序列+线段树】

题目地址:http://poj.org/problem?id=2828 Sample Input 4 0 77 1 51 1 33 2 69 4 0 20523 1 19243 1 3890 0 31492 Sample Output 77 33 69 51 31492 20523 3890 19243 Hint The figure below shows how the Little Cat found out the final order of people in the queue d

HDU 4521 小明系列问题——小明序列 (线段树维护DP)

题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include

P2023 [AHOI2009]维护序列 --线段树

题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. 输入输出格式 输入格式: 第一行两个整数N和P(1≤P≤1000000000).第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N).第三行有一个整