【题意概述】

  给出一个有左括号和右括号的序列,左边的左括号和右边的右括号可以合并。现在要求你维护这个序列,支持两种操作:

  1,翻转某个位置的括号;

  2,查询区间[L,R]合并后第k个括号在原序列中的位置,如果k超过区间合并后的括号总数,输出-1.

【题解】

  首先我们可以发现,对于一个区间,合并后的结果一定是若干个右括号、若干个左括号的形式。即))))(((((...

  线段树上维护两个标记,区间左边的右括号数量cl、区间右边的左括号数量cr。合并的时候把左区间的cr和右区间的cl抵消一下,然后计算新的cl、cr即可。

  这样对于询问,我们可以快速确定它是左括号还是右括号,或者不满足题意输出-1。但我们怎么求第k个左/右括号在原序列中的位置呢?我的做法是询问的时候把经过的各个区间记录一下,逐个区间查找,如果k落在当前区间,就进入线段树进行查找,走到叶子结点就是答案。也可以直接在线段树上查找,不把区间取出来。

  

 #include<cstdio>
#include<algorithm>
#define rg register
#define N 200010
#define ls (u<<1)
#define rs (u<<1|1)
using namespace std;
int T,n,m,f[N],s[N],cnt,rt;
char c[N];
struct tree{
int l,r,cl,cr;
}a[N<<];
struct rec{
int cl,cr;
};
inline int read(){
int k=; char c=getchar();
while(c<''||c>'')c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k;
}
inline void pushup(int u){
a[u].cl=a[ls].cl; a[u].cr=a[rs].cr;
int tmp=a[ls].cr-a[rs].cl;
if(tmp>) a[u].cr+=tmp;
else a[u].cl-=tmp;
}
void build(int u,int l,int r){
a[u].l=l; a[u].r=r; a[u].cl=a[u].cr=;
if(l<r){
int mid=(l+r)>>;
build(ls,l,mid); build(rs,mid+,r);
pushup(u);
}
else{
if(f[l]==) a[u].cr=; else a[u].cl=;
}
}
void update(int u,int pos){
if(a[u].l==a[u].r){
a[u].cl^=; a[u].cr^=; return;
}
int mid=(a[u].l+a[u].r)>>;
if(pos<=mid) update(ls,pos);
else update(rs,pos);
pushup(u);
}
rec query(int u,int l,int r){
if(l<=a[u].l&&a[u].r<=r){
s[++cnt]=u;
rec tmp;
tmp.cl=a[u].cl; tmp.cr=a[u].cr;
return tmp;
}
int mid=(a[u].l+a[u].r)>>;
rec ret,L,R; ret.cl=ret.cr=;
if(l<=mid) ret=L=query(ls,l,r);
if(r>mid) ret=R=query(rs,l,r);
if(l<=mid&&r>mid){
ret.cl=L.cl; ret.cr=R.cr;
int tmp=L.cr-R.cl;
if(tmp>) ret.cr+=tmp;
else ret.cl-=tmp;
}
return ret;
}
int findl(int u,int k){
if(a[u].l==a[u].r) return a[u].l;
if(a[ls].cl>=k) return findl(ls,k);
return findl(rs,k-a[ls].cl+a[ls].cr);
}
int findr(int u,int k){
if(a[u].l==a[u].r) return a[u].l;
if(a[rs].cr>=k) return findr(rs,k);
return findr(ls,k-a[rs].cr+a[rs].cl);
}
int main(){
T=read();
while(T--){
n=read(); m=read();
scanf("%s",c+);
for(rg int i=;i<=n;i++) if(c[i]=='(') f[i]=; else f[i]=;
build(,,n);
while(m--){
int opt=read();
if(opt==){
int x=read();
update(,x);
}
else{
int l=read(),r=read(),k=read(); cnt=;
rec tmp=query(,l,r);
if(tmp.cl+tmp.cr<k){
puts("-1");
continue;
}
if(tmp.cl>=k){
for(rg int i=;i<=cnt;i++){
if(a[s[i]].cl>=k){
rt=s[i]; break;
}
else k+=a[s[i]].cr-a[s[i]].cl;
}
printf("%d\n",findl(rt,k));
}
else{
k=tmp.cl+tmp.cr-k+;
for(rg int i=cnt;i;i--){
if(a[s[i]].cr>=k){
rt=s[i]; break;
}
else k+=a[s[i]].cl-a[s[i]].cr;
}
printf("%d\n",findr(rt,k));
}
}
}
}
return ;
}

HDU 5217 Brackets的更多相关文章

  1. 【hdu 5217】Brackets

    Description Miceren likes playing with brackets. There are N brackets on his desk forming a sequence ...

  2. 2015 "BestCoder Cup" Champion

    这场比赛我没有参加,不过就算参加了也估计是被完虐.于是看着题解把大部分题目都搞了一遍. T1:Movie(hdu 5214) 题目大意: 给出N个区间,问能否选出3个互不相交的区间. N<=10 ...

  3. BestCoder Round #32

    问题描述 目前,我们用PM2.5的含量来描述空气质量的好坏.一个城市的PM2.5含量越低,它的空气质量就越好.所以我们经常按照PM2.5的含量从小到大对城市排序.一些时候某个城市的排名可能上升,但是他 ...

  4. 【HDU 5184】 Brackets (卡特兰数)

    Brackets Problem Description We give the following inductive definition of a “regular brackets” sequ ...

  5. HDU——PKU题目分类

    HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...

  6. HDU 1866 A + B forever!

    A + B forever! Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  9. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

随机推荐

  1. 24. [Ext JS 4] 实战之Load Mask(加载遮罩)的显示与隐藏

    转自:https://blog.csdn.net/oscar999/article/details/27176791

  2. Eclipse导入Java 的jar包的方法

    打开eclipse1.右击要导入jar包的项目,点properties 2.左边选择java build path,右边选择libraries 3.选择add External jars 4.选择ja ...

  3. http-2.2

    HTTP-2.2 httpd 配置文件的组成: grep "Section" /etc/httpd/conf/httpd.conf ### Section 1: Global En ...

  4. 源码阅读之LinkedHashMap(JDK8)

    概述 LinkedHashMap继承自HashMap,实现了Map<K,V>接口.其内部还维护了一个双向链表,在每次插入数据,或者访问.修改数据时,会增加节点.或调整链表的节点顺序.以决定 ...

  5. spring 简单实现BeanFactory(转)

    原文地址: http://blog.csdn.net/mlc1218559742/article/details/52776160 有没有发现上面的代码与利用反射实现工厂模式的代码很相似.对,你没有看 ...

  6. Linux 常规操作指南

    1.修改Linux服务器别名 临时修改: vim /etc/hostname  修改别名 永久修改: vim  /etc/sysconfig/network  添加 HOSTNAME=别名 重启服务器 ...

  7. ADSI和其他内容

    ADSI (Active Directory Services Interface)是Microsoft推出的一项技术,它统一了许多底层服务的编程接口,程序员可以使用一致的对象技术来访问这些底层服务. ...

  8. 二分搜索 POJ 1064 Cable master

    题目传送门 /* 题意:n条绳子问切割k条长度相等的最长长度 二分搜索:搜索长度,判断能否有k条长度相等的绳子 */ #include <cstdio> #include <algo ...

  9. c++利用jsoncpp libcurl 构造http 包(原)

    我们手游要接入uc九游进行测试,要用http向uc那边的sdk 服务器post  json数据. 虽然他们提供了php,java还有c#的服务端demo,但是我们服务器是C++写的,我实在不想中间再转 ...

  10. git 删除分支如何恢复

    强制删除了一个分支而后又想重新使用这个分支,该怎么找回该分支上的代码呢? 一:问题描述: 今天师父说上线几个功能,让我把开发的分支推送到远程.当打开git就傻眼了,之前开发好的分支被我删除了,就连推送 ...