【题意概述】

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

  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. Java工作中常用到的工具

    刚看但网上一篇Java最流行工具的文章,结合自己日常应用总结一下开发工作中常用到的工具. 一,Java版本,jdk8,也是Java普及最快的版本,除了本身性能提升外,新增的函数式编程特性也让开发效率更 ...

  2. Android下载资源

    下面提供了源码下载地址,供有兴趣的朋友下载, android音乐播放器源码   由于本人才疏学浅,有很多地方不够完善,希望大家指证. 免费下载地址在 http://linux.linuxidc.com ...

  3. 转贴:CSS伪类与CSS伪元素的区别及由来具体说明

    关于两者的区别,其实是很古老的问题.但是时至今日,由于各种网络误传以及一些不负责任的书籍误笔,仍然有相当多的人将伪类与伪元素混为一谈,甚至不乏很多CSS老手.早些年刚入行的时候,我自己也被深深误导,因 ...

  4. bzoj 1664: [Usaco2006 Open]County Fair Events 参加节日庆祝【dp+树状数组】

    把长度转成右端点,按右端点排升序,f[i]=max(f[j]&&r[j]<l[i]),因为r是有序的,所以可以直接二分出能转移的区间(1,w),然后用树状数组维护区间f的max, ...

  5. [Swift]通天遁地Swift

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. 慕课网JavaScript函数1-20 作业:函数的基础封装

    1-20 作业 小伙伴们,掌握了JavaScript的语法.流程控制语句以及函数,接下来让我们运用所学知识完成如gif图所示的效果——计算自己出生那天是该年当中的第几天. gif效果图如下: 任务描述 ...

  7. Joseph UVA 1452 Jump

    题目传送门 /* 数学:约瑟夫环问题的变形,首先定义f[i]表示剩下i个人时,最后一个选出的人,有个公式:f[i] = (f[i-1] + m) % i f[1] = 0(编号从0开始),那么类似最后 ...

  8. magento后台开发学习笔记(入门实例向)

    目的是做一个grid,参考博客http://www.sunzhenghua.com/magento-admin-module-development-part1-grid-forms-tabs-con ...

  9. Spring.Net学习笔记(6)-方法注入

    一.开发环境 系统:win10 编译器:VS2013 二.涉及程序集 Spring.Core.dll 1.3.1 Common.Logging.dll 三.开发过程 1.项目结构 2.编写Mobile ...

  10. Code Kata:大整数四则运算—乘法 javascript实现

    上周练习了加减法,今天练习大整数的乘法运算. 采取的方式同样为竖式计算,每一位相乘后相加. 乘法函数: 异符号相乘时结果为负数,0乘任何数都为0 需要调用加法函数 因为输入输出的为字符串,需要去除字符 ...