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 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
随机推荐
- 2017阿里给Java开发者的两个福利
一.<Java开发规约> 无规矩不成方圆 无规范不能协作. 2017年开春之际,诚意献上重磅大礼:阿里巴巴Java开发手册,首次公开阿里官方Java代码规范标准.这套Java统一规范标准将 ...
- UVa10288 Coupons 分数模版
UVa10288 题目非常简单, 答案就是 n/n+n/(n-1)+...+n/1; 要求分数输出.套用分数模板.. #include <cstdio> #include <cstr ...
- Tomcat优化和JVM分析工具
Tomcat的常见优化和JVM常见分析工具 Tomcat的常用优化配置 (1) 内存空间: /etc/sysconfig/tomcat JAVA_OPTS="-server -Xms32g ...
- bzoj 4756: [Usaco2017 Jan]Promotion Counting【dfs+树状数组】
思路还是挺好玩的 首先简单粗暴的想法是dfs然后用离散化权值树状数组维护,但是这样有个问题就是这个全局的权值树状数组里并不一定都是当前点子树里的 第一反应是改树状数组,但是显然不太现实,但是可以这样想 ...
- redis在linux安装和开机启动和结合php运用方法一
第一部分:安装redis 希望将redis安装到此目录 1 /usr/local/redis 希望将安装包下载到此目录 1 /usr/local/src 那么安装过程指令如下: 1 2 3 4 5 6 ...
- random模块思维导图
- 题解报告:poj 2386 Lake Counting(dfs求最大连通块的个数)
Description Due to recent rains, water has pooled in various places in Farmer John's field, which is ...
- 全面学习ORACLE Scheduler特性(10)管理Chains
5.2 管理Chains 5.2.1 修改Chains属性 基本上碰到修改CHAIN属性的机率不会太大,因此确实没啥可修改的,对于CHAIN对象来说,能够修改的属性只有两个:evaluation_ ...
- 289 Game of Life 生命的游戏
假设有一个大小为m*n的板子,有m行,n列个细胞.每个细胞有一个初始的状态,死亡或者存活.每个细胞和它的邻居(垂直,水平以及对角线).互动规则如下:1.当前细胞存活时,周围低于2个存活细胞时,该细胞死 ...
- 2017-11-28 Html-浅谈如何正确给table加边框
一般来说,给表格加边框都会出现不同的问题,以下是给表格加边框后展现比较好的方式 <style> table,table tr th, table tr td { border:1px so ...