码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-04-29 23:32:38      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:括号   and   clu   problems   链接   位置   space   span   树状数组   

 

【题目链接】 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(扫描线+树状数组)

标签:括号   and   clu   problems   链接   位置   space   span   树状数组   

原文地址:http://www.cnblogs.com/forever97/p/codeforces380c.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!