CodeForces 380C Sereja and Brackets(扫描线+树状数组)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces 380C Sereja and Brackets(扫描线+树状数组)相关的知识,希望对你有一定的参考价值。

 

【题目链接】 http://codeforces.com/problemset/problem/380/C

 

【题目大意】

  给出一个括号序列,求区间内左右括号匹配的个数。

 

【题解】

  我们发现对于每个右括号,其匹配的左括号是固定的,
  我们保存每个右括号匹配的左括号位置,
  对区间询问进行线扫描,将扫描的区间右端点及其之前所有的右括号对应的左括号位置做标记,
  只要查询询问区间的标记个数就是答案,这个可以用树状数组维护。

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring> 
const int N=1000010;
using namespace std;
typedef long long LL;
int i,n,m,ans,res[N],c[N];
struct Q{int l,r,id;}ask[N];
bool cmp(Q a,Q b){return a.r<b.r;}
int st[N],top,pre[N];
char s[N];
int main(){
    while(~scanf("%s",s+1)){
        memset(c,0,sizeof(c));
        memset(res,0,sizeof(res));
        n=strlen(s+1); scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&ask[i].l,&ask[i].r),ask[i].id=i;
        top=0; 
        for(int i=1;i<=n;i++){
            if(s[i]==‘(‘)st[++top]=i;
            else pre[i]=top?st[top--]:n+1;
        }sort(ask+1,ask+m+1,cmp);
        int pos=0;
        for(int i=1;i<=m;i++){
            while(pos<ask[i].r){pos++;if(s[pos]==‘)‘)for(int x=pre[pos];x<=n;x+=x&-x)c[x]++;} 
            for(int x=ask[i].r;x;x-=x&-x)res[ask[i].id]+=c[x];
            for(int x=ask[i].l-1;x;x-=x&-x)res[ask[i].id]-=c[x];
        }for(int i=1;i<=m;i++)printf("%d\n",res[i]<<1);
    }return 0;
}

以上是关于CodeForces 380C Sereja and Brackets(扫描线+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

CF 368B Sereja and Suffixes(DP?)

[Codeforces 425A] Sereja and Swaps

Sereja and Swaps CodeForces - 426C

Codeforces 425A Sereja and Swaps(暴力枚举)

CodeForces - 367E:Sereja and Intervals(组合数&&DP)

Codeforces Round #243 (Div. 2)——Sereja and Table