Flipping Parentheses(CSU1542 线段树)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1542
赛后发现这套题是2014东京区域赛的题目,看了排名才发现自己有多low = =!
题目大意是这样的,给一个已经匹配了的括号序列,现每次操作就是在位置p将这个位置的括号反转,问要达到将这个序列重新变成匹配序列,最左侧能够操作第几个括号达到目的。
这里,我的思路是用一个数组a,a[i]表示的是前i个括号,左括号'('与右括号')'的数量之差,题目数据就可以表示为:
s: ( ( ( ) ) )
a: 1 2 3 2 1 0
这样,一个匹配的括号序列对应的数组一定满足两个条件:1、数组没有一个元素为负 2、数组是以0结尾
现操作时,若是将'(' 转化为')' ,比如将位置4的括号反转,对应数组:
s: ( ( ( ( ) )
a: 1 2 3 4 3 2
可以看做是将数组位置4以后的每个元素都+2(反之,若是')'转化为'(',那么就是那个位置以后每个元素都-2)
可以看到:
对应第一种操作,将'(' 转化为')', 要达到匹配序列,只需要将括号序列里的第一个右括号')'翻转即可(因为此时为+2操作,又只可以操作右括号,所以操作第一个必然是最优的)
对应第二种操作,将')'转化为'(',则是找到从末尾往前找到最早的一个a[p]>=2的位置p,且a[p ~ n] >= 2全部成立,(因为是-2操作,所以必须保证在-2前这个数是>=2的)
计算时,可以使用线段树(因为有区间操作),节点保存的内容包括左右括号数量之差a,延时标记s,以及f = a[i] - i的值(若a[i] - i < 0,说明在区间[1, i]一定存在一个左括号,供查找第一个左括号时使用),而若要找到从后往前最长连续的a[p ~ n] >= 2的位置p,只需要判断区间的最小值是否>=2,查找方式与上一个类似。
查询时区间保存的是这个区间的 a 值和 f 值的最小值。区间修改+极值查询。
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++) template<class T> T CMP_MIN(T a, T b) { return a < b; }
template<class T> T CMP_MAX(T a, T b) { return a > b; }
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; } //typedef __int64 LL;
typedef long long LL;
const int MAXN = ;
const int MAXM = ;
const double eps = 1e-; int n, q, p, len;
char s[]={""};
struct Node {
int f, a, s;
}t[<<]; char rev(char c) { return (c == '(') ? ')' : '('; } void buildTree(int k, int L, int R, int p, int a)
{
t[k].s = ;
if(L == R) {
t[k].f = a - L; t[k].a = a;
return ;
}
int mid = (L + R) >> ;
if(p > mid) buildTree(rson, p, a);
else buildTree(lson, p, a);
t[k].f = min(t[k<<].f, t[k<<|].f);
t[k].a = min(t[k<<].a, t[k<<|].a);
} void init()
{
mem0(t);
int sum = ;
len = strlen(s) - ;
rep (i, , len) {
sum += (s[i] == '(') ? : -;
buildTree(, , len, i, sum);//建树
}
} //向下传延时标记
void pushDown(int k)
{
t[k<<].s += t[k].s; t[k<<].a += t[k].s; t[k<<].f += t[k].s;
t[k<<|].s += t[k].s; t[k<<|].a += t[k].s; t[k<<|].f += t[k].s;
t[k].s = ;
} //更新操作,将区间[p, len]的所有值都+val
void update(int k, int L, int R, int p, int val)
{
if(p <= L) {
t[k].s += val;
t[k].a += val;
t[k].f += val;
return ;
}
pushDown(k);
int mid = (L + R) >> ;
if(p <= mid) update(lson, p, val);//左侧可能需要更新
update(rson, p, val);//右侧是一定要更新的,因为需要更新的区间为[p, len]
t[k].f = min(t[k<<].f, t[k<<|].f);
t[k].a = min(t[k<<].a, t[k<<|].a);
} //查询最左侧的右括号
int query1(int k, int L, int R)
{
if(L == R) return L;
int mid = (L + R) >> ;
pushDown(k);
if(t[k<<].f < ) return query1(lson);
return query1(rson);
} //查询从len往前连续的最长的满足a>=2的点,也就是最后一个<2的位置+1
int query2(int k, int L, int R)
{
if(L == R) return min(len, L + );
int mid = (L + R) >> ;
pushDown(k);
if(t[k<<|].a < ) return query2(rson);
return query2(lson);
} int main()
{
//FIN;
while(~scanf("%d %d%*c %s", &n, &q, s + )) {
init();
rep (i, , q - ) {
scanf("%d", &p);
s[p] = rev(s[p]); update(, , len, p, s[p] == ')' ? - : );
if(s[p] == ')') p = query1(, , len);//find first )
else p = query2(, , len); //find last < 2
s[p] = rev(s[p]); update(, , len, p, s[p] == ')' ? - : );
printf("%d\n", p);
}
}
return ;
}
Flipping Parentheses(CSU1542 线段树)的更多相关文章
- Codeforces Gym 100803G Flipping Parentheses 线段树+二分
Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...
- CSU - 1542 Flipping Parentheses (线段树)
CSU - 1542 Flipping Parentheses Time Limit: 5000MS Memory Limit: 262144KB 64bit IO Format: %lld ...
- Flipping Parentheses~Gym 100803G
Description A string consisting only of parentheses '(' and ')' is called balanced if it is one of t ...
- CSUOJ 1542 Flipping Parentheses
ACM International Collegiate Programming Contest Asia Regional Contest, Tokyo, 2014–10–19 Problem G ...
- spoj IITWPC4F - Gopu and the Grid Problem 线段树
IITWPC4F - Gopu and the Grid Problem no tags Gopu is interested in the integer co-ordinates of the ...
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...
- hdu 5831 Rikka with Parenthesis II 线段树
Rikka with Parenthesis II 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5831 Description As we kno ...
- hdu 5338 ZZX and Permutations (贪心+线段树+二分)
ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- HDU 6155 Subsequence Count 线段树维护矩阵
Subsequence Count Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Oth ...
随机推荐
- 51nod1204 Parity
如果sm[j]和sm[i]奇偶性相同,那么(i+1,j)个数为偶数如果奇偶性相同看成是朋友,不同的看成是敌人,那么就跟bzoj1370的做法差不多了. 如果奇偶性相同,就将x和y合并,x+n,y+n合 ...
- link cut tree 入门
鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...
- [转] POJ计算几何
转自:http://blog.csdn.net/tyger/article/details/4480029 计算几何题的特点与做题要领:1.大部分不会很难,少部分题目思路很巧妙2.做计算几何题目,模板 ...
- BZOJ 4557 侦查守卫
好迷的树形dp... #include<iostream> #include<cstdio> #include<cstring> #include<algor ...
- DOM对象常用对象的方法和属性
HTML文档中的常用节点类型: 接口 nodeType 备注 Element 1 元素节点 Text 3 文本节点 Document 9 Document Comment 8 注释文本 Docum ...
- 【原创】牛顿法和拟牛顿法 -- BFGS, L-BFGS, OWL-QN
数据.特征和数值优化算法是机器学习的核心,而牛顿法及其改良(拟牛顿法)是机器最常用的一类数字优化算法,今天就从牛顿法开始,介绍几个拟牛顿法算法.本博文只介绍算法的思想,具体的数学推导过程不做介绍. 1 ...
- php时区测试
php里面关于时间的函数有date,time,strtotime,gmdate等,里面只要和时间字符串相关的基本都收到时区的影响,所以时间戳才是唯一稳定时间记录,因为标准都是统一的.这里联想到数据库的 ...
- php 计算本月第一天 本月最后一天 下个月第一天
本文转载自 http://jin541223.blog.163.com/blog/static/1637398052011111233018533/ //本周第一天(星期日为一周开始) echo ...
- ios import和@class的区别
二者的区别在于: 1.import会包含这个类的所有信息,包括实体变量和方法,而@class只是告诉编译器,其后面声明的名称是类的名称,至于这些类是如何定义的,暂时不用考虑,后面会再告诉你. 2.在头 ...
- Asp.net 身份验证方式?
[Forms 身份验证] 通过其可将没有通过身份验证的请求重定向到使用 HTTP 客户端重定向的 HTML 窗体的系统.用户提供凭据并提交该窗体.如果应用程序验证该请求,系统就会发出包含凭据或密钥的 ...