CSUOJ 1542 线段树解决括号反向问题
题目大意:
根据初始给定的合法的小括号排序,每次进行一个操作,将第a位的括号反向,找到一个尽可能靠前的括号反向后是整个括号排列合法
数据量十分大,不断进行查询,要用线段树进行logn的复杂度的查询
首先最简单的考虑 '('->')' , 稍微想一下可以知道因为要尽可能靠前,所以其实把最前面的那个 )改成 ( 即可,这里我就用 minn[] 数组记录区间内最早出现的 ) 的下标
然后是考虑 ')'->'(' , 我们可以倒着字符串来看,从后往前每次出现一个 ) 都记录加1 , 那么每次遇到一个 ( 就抵消1 , 那么当遇到 (没东西抵消时,说明这个是离尾部最远的不合法的符号,离尾部最远,那么就可以理解为离起点最近
具体怎么写的话就是可以将 '(' 看作 1 , ')' 看作-1 , 利用一个数组 minsum[] 记录区间内前缀和的最小值
对于一个线段树来说如果那个符号的位置出现在左子树的区间上,那么右子树中的所有前缀和都必然 >=2
所以查询就很容易得到 if(sum[rs] < 2) ans = 右子树的查询,else ans = 左子树的查询
但再想想的话,返回的值不能是当前下标 , 而是下标+1;
因为根据前面所讲,你所需要修改的位置 i 是 i 后面的数相加和正好为0的
也就是说到达i的前缀之和正好是2
而 第 i-1 位的前缀和正好为1,每次不断判断找 < 2的点,那么最后查询到的是i-1
也就是必须要加个1才能到达我需要改的位置
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define ls o<<1
#define rs o<<1|1
#define define_m int m=(l+r)>>1
const int N = ;
const int INF = 0x3f3f3f3f;
int minn[N<<] , minsum[N<<] , a[N] , add[N<<];
char str[N]; void push_up(int o)
{
minsum[o]=min(minsum[ls] , minsum[rs]);
minn[o]=min(minn[ls] , minn[rs]);
} void push_down(int o)
{
if(add[o]){
add[ls]+=add[o];
add[rs]+=add[o];
minsum[ls]+=add[o];
minsum[rs]+=add[o];
add[o]=;
}
} void build(int o , int l , int r)
{
add[o]=;
if(l == r) {
minn[o] = str[l]==')'?l:INF;
minsum[o]=a[l];
return;
}
define_m;
build(ls , l , m);
build(rs , m+ , r);
push_up(o);
} void update(int o , int l , int r , int s , int t , int v)
{
if(l>=s && r<=t){
minsum[o]+=v;
add[o]+=v;
return;
}
push_down(o);
define_m;
if(m>=s) update(ls , l , m , s , t , v);
if(m<t) update(rs , m+ , r ,s , t , v);
minsum[o]=min(minsum[ls] , minsum[rs]);
} void update1(int o , int l , int r , int pos)
{
if(l == r && l == pos){
minn[o] = (str[l]==')'?l:INF);
return;
}
push_down(o);
define_m;
if(m >= pos) update1(ls , l , m ,pos);
else update1(rs , m+ , r , pos);
minn[o] = min(minn[ls] , minn[rs]);
} int query(int o , int l , int r , int n)
{
// cout<<"o: "<<o<<" l: "<<l<< " r: "<<r<<" left: "<<minsum[ls]<<" right: "<<minsum[rs]<<endl;
if(l==r) return l+;
push_down(o);
define_m;
if(minsum[rs]<) return query(rs , m+ , r , n);
else return query(ls , l , m , n);
} int main()
{
// freopen("a.in" , "r" , stdin);
int n , m , pos;
while(scanf("%d%d" , &n , &m) != EOF)
{
scanf("%s" , str+);
for(int i= ; i<=n ; i++){
a[i]=a[i-]+(str[i]=='('?:-);
}
build( , , n);
int res;
for(int i= ; i<m ; i++){
scanf("%d" , &pos);
if(str[pos] == '('){
str[pos] = ')';
update1( , , n , pos);
update( , , n , pos , n , -);
res = minn[];
str[res] = '(';
update1( , , n , res);
}
else{
str[pos] = '(';
update1( , , n , pos);
update( , , n , pos , n , );
res = query( , , n , n);
str[res] = ')';
update1( , , n , res);
}
update( , , n , res , n , str[res] == '('?:-);
printf("%d\n" , res);
}
}
return ;
}
CSUOJ 1542 线段树解决括号反向问题的更多相关文章
- hdu 1542 线段树扫描(面积)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治
这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...
- BZOJ 1095 捉迷藏(线段树维护括号序列)
对于树的一个括号序列,树上两点的距离就是在括号序列中两点之间的括号匹配完之后的括号数... 由此可以得出线段树的做法.. #include<cstdio> #include<iost ...
- [板子]用线段树解决ST表问题
ST表可以参考:http://blog.csdn.net/whistlena/article/details/52191463 简单说就是区间RMQ最值问题. 对解决这种问题,线段树不用用啥啊. 扔一 ...
- hdu 1542 线段树+扫描线 学习
学习扫描线ing... 玄学的东西... 扫描线其实就是用一条假想的线去扫描一堆矩形,借以求出他们的面积或周长(这一篇是面积,下一篇是周长) 扫描线求面积的主要思想就是对一个二维的矩形的某一维上建立一 ...
- hdu 1542 线段树之扫描线之面积并
点击打开链接 题意:给你n个矩形,求它们的面积,反复的不反复计算 思路:用线段树的扫描线完毕.将X坐标离散化后,从下到上扫描矩形,进行各种处理,看代码凝视把 #include <stdio.h& ...
- BZOJ 1095: [ZJOI2007]Hide 捉迷藏(线段树维护括号序列)
这个嘛= =链剖貌似可行,不过好像代码长度很长,懒得打(其实是自己太弱了QAQ)百度了一下才知道有一种高大上的叫括号序列的东西= = 岛娘真是太厉害了,先丢链接:http://www.shuizilo ...
- BZOJ1095: [ZJOI2007]Hide 捉迷藏【线段树维护括号序列】【思维好题】
Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...
- CodeForces-380C:Sereja and Brackets(线段树与括号序列)
Sereja has a bracket sequence s1, s2, ..., sn, or, in other words, a string s of length n, consistin ...
随机推荐
- 题解报告:poj 2299 Ultra-QuickSort(BIT求逆序数)
Description In this problem, you have to analyze a particular sorting algorithm. The algorithm proce ...
- post和get提交服务器编码过程
参考资料:http://blog.csdn.net/z55887/article/details/46975679 先说出一个知识点: 如果浏览器端编码是UTF-8,那在服务器端解决乱码问题的方法有两 ...
- [转]Android项目快速开发框架探索(Mysql + OrmLite + Hessian + Sqlite)
前言 结合之前所用的ormlite和hessian,再加上SAE已经支持JAVA,把服务端切换到JAVA,也就有了本文.使用hessian来做数据传输,ormlite来实现客户端与服务端的数据存储,极 ...
- 解决okHttp使用https抛出stream was reset: PROTOCOL_ERROR的问题
昨天在做Android接口调用的时候,api接口是https的,用okhttp抛出: okhttp3.internal.http2.StreamResetException: stream was r ...
- VMware虚拟机中涉及的3种常见网络模式
桥接模式.这种模式下,虚拟机和物理机连的是同一个网络,虚拟机和物理机是并列关系,地位是相当的.比如你家如果有用路由器,那么你的电脑和你的手机同时连接这个路由器提供的Wi-Fi,那么它们的关系就是这种模 ...
- js实现元素水平垂直居中
之前有写过css/css3实现元素的水平和垂直居中的几种方法点我,但是css3属性不是所有浏览器都能兼容的,今天写下js实现未知宽高的元素的水平和垂直居中. <!DOCTYPE html> ...
- 锐动SDK应用于行车记录仪
方案架构 手机端直播与录播功能忠实记录旅途中各种突发事件,还原事实真相,与家人和朋友分享沿途美景,一同感受美妙之旅. 强大的视频编辑功能,像编辑图片一样给视频添加各种滤镜,配音,配乐,标题文字等特效. ...
- Python界面编程之六----布局
布局(转载于–学点编程吧)通过实践可知采用了布局之后能够让我们的程序在使用上更加美观,不会随着窗体的大小发生改变而改变,符合我们的使用习惯. 绝对位置程序员以像素为单位指定每个小部件的位置和大小. 当 ...
- create_module - 生成一条可加载模块记录
总览 #include <linux/module.h> caddr_t create_module(const char *name, size_t size); 描述 create_m ...
- 09C++指针
指针 6.1 指针的概念 请务必弄清楚一个内存单元的地址与内存单元的内容这两个概念的区别.在程序中一般是通过变量名来对内存单元进行存取操作的.其实程序经过编译以后已经将变量名转换为变量的地址,对变量值 ...