HDU 5217 Brackets

【题意概述】
给出一个有左括号和右括号的序列,左边的左括号和右边的右括号可以合并。现在要求你维护这个序列,支持两种操作:
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的更多相关文章
- 【hdu 5217】Brackets
Description Miceren likes playing with brackets. There are N brackets on his desk forming a sequence ...
- 2015 "BestCoder Cup" Champion
这场比赛我没有参加,不过就算参加了也估计是被完虐.于是看着题解把大部分题目都搞了一遍. T1:Movie(hdu 5214) 题目大意: 给出N个区间,问能否选出3个互不相交的区间. N<=10 ...
- BestCoder Round #32
问题描述 目前,我们用PM2.5的含量来描述空气质量的好坏.一个城市的PM2.5含量越低,它的空气质量就越好.所以我们经常按照PM2.5的含量从小到大对城市排序.一些时候某个城市的排名可能上升,但是他 ...
- 【HDU 5184】 Brackets (卡特兰数)
Brackets Problem Description We give the following inductive definition of a “regular brackets” sequ ...
- HDU——PKU题目分类
HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...
- HDU 1866 A + B forever!
A + B forever! Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
随机推荐
- Create schema error (unknown database schema '')
Andrey Devyatka 4 years ago Permalink Raw Message Hi,Please tell me, can I use the static library in ...
- Python Matplotlib模块--pyplot
#-*- coding: utf- -*- ''' numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=No ...
- Linux压缩命令(zip/gz/bz2/tar/tar.gz/tar.bz2)
一.Linux的压缩格式 .zip . gz . bz2 .tar 1..zip格式(Linux和Windows是可以互传的) 压缩命令 语法:zip 文件名.zip 文件名 ------压缩 ...
- 数据据操作 tp5
数据库操作-DB类 学习手册 数据库配置 注意1:在TP里面,可以在模块下面单独的建立一个database.php配置文件,代表这个模块就使用配置的这个数据库 注意2:我们可以在config.php里 ...
- Jsp四个作用域page、request、session和application的区别
1.简单说 page指当前页面.在一个jsp页面里有效 2.request 指从http请求到服务器处理结束,返回响应的整个过程.在这个过程中使用forward方式跳转多个jsp.在这些页面里你都可 ...
- C#---数据库访问通用类、Access数据库操作类、mysql类 .
//C# 数据库访问通用类 (ADO.NET)using System;using System.Collections.Generic;using System.Text;using System. ...
- CSS 样式的优先级小结
1. 同一元素引用了多个样式时,排在后面的样式属性的优先级高 例如,下面的 div,同时引用了 [.default] 和 [.user] 中的样式,其中 [.user] 样式中的 width 属性会替 ...
- 258 Add Digits 各位相加
给一个非负整数 num,反复添加所有的数字,直到结果只有一个数字.例如:设定 num = 38,过程就像: 3 + 8 = 11, 1 + 1 = 2. 由于 2 只有1个数字,所以返回它.进阶:你可 ...
- Python之数据规整化:清理、转换、合并、重塑
Python之数据规整化:清理.转换.合并.重塑 1. 合并数据集 pandas.merge可根据一个或者多个不同DataFrame中的行连接起来. pandas.concat可以沿着一条轴将多个对象 ...
- tensorFlow资源
1,[莫烦]Tensorflow tutorials (Eng Sub) 神经网络 http://www.bilibili.com/video/av10118932/index_35.html#pag ...