CSU - 1542 Flipping Parentheses (线段树)
来源:互联网 发布:董宇阳,知乎 编辑:程序博客网 时间:2024/05/01 03:48
CSU - 1542
Flipping Parentheses
Time Limit: 5000MS Memory Limit: 262144KB 64bit IO Format: %lld & %llu
Description
Input
Output
Sample Input
6 3((()))431
Sample Output
221
Hint
题意:先给出一个符合括号匹配的字符串,然后Q次操作
每次操作将某个括号反转,问将哪个括号反转能使字符串的括号再次匹配,位置要取最左端符合条件的。
可以利用前缀和 比如(())那么前缀和分别就是1,2,1,0。观察到,平衡时前缀和都是等于0的。
通过前缀和,我们可以发现规律:
将一个'('翻转成')'会使得从当前位置开始到字符串最后的前缀和都会减2
如果将')'翻转成'(',同理,此位置开始以后的所有前缀和都要加2
而如果减去了2,那如何增加2抵消掉之前的影响,得到最后的后缀和为零
而减去2的话肯定是'('翻转成')',那么如何加一个数抵消掉')'的影响
如果是将p点翻转的话,肯定是从[1,p],找一个')',将')'翻转成'('
有没有发现规律,如果是'('翻转成')',则是在之前的区间将')'翻转成'(',那么将')'翻转成'('时,就是往后,找一个'('将其'('翻转成')'
维护该区间的最小值即可,只要最小值不小于2,那么该区间的所有值都不会小于2
提供一个朋友的详解地址,说的很好:http://blog.csdn.net/qwb492859377/article/details/47357553
/*Author: 2486Memory: 32700 KBTime: 760 MSLanguage: C++Result: AcceptedVJ RunId: 4340427Real RunId: 149963*/#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;#define lson rt << 1, l, mid#define rson rt << 1|1, mid + 1, r#define root 1, 1, nconst int MAXN = 5e5 + 5;const int INF = 0x3f3f3f3f;int sum[MAXN << 2];int Min[MAXN << 2],col[MAXN << 2],val[MAXN << 2];int S,n,m;char str[MAXN];void pushup_1(int rt) { sum[rt] = min(sum[rt << 1], sum[rt << 1|1]);}void build(int rt, int l, int r) { col[rt] = 0; if(l == r) { val[rt] = (str[l] == '(' ? 1 : -1); S += val[rt]; Min[rt] = S; sum[rt] = val[rt] == 1 ? INF : l; return; } int mid = (l + r) >> 1; build(lson); build(rson); pushup_1(rt); Min[rt] = min(Min[rt << 1], Min[rt << 1|1]);}int update_1(int p, int rt, int l, int r) { if(l == r) { int tmp = val[rt]; val[rt] *= -1; sum[rt] = tmp == 1 ? p : INF; return tmp; } int mid = (l + r) >> 1, ret; if(p <= mid) ret = update_1(p, lson); if(p > mid) ret = update_1(p, rson); pushup_1(rt); return ret;}void pushdown(int rt) { if(col[rt]) { col[rt << 1] += col[rt]; col[rt << 1|1] += col[rt]; col[rt] = 0; }}void pushup_2(int rt) { Min[rt] = min(Min[rt << 1] + col[rt << 1], Min[rt << 1|1] + col[rt << 1|1]);}void update_2(int L, int R, int c,int rt, int l, int r) { if(L <= l && r <= R) { col[rt] += c; return; } pushdown(rt); int mid = (l + r) >> 1; if(L <= mid) update_2(L, R, c, lson); if(R > mid) update_2(L, R, c, rson); pushup_2(rt);}int query(int rt, int l,int r) { if(Min[rt] + col[rt] >= 2) return l; if(l == r) return r + 1; pushdown(rt); int mid = (l + r) >> 1; int ret; if(Min[rt << 1|1] + col[rt << 1|1] >= 2) ret = query(lson); else ret = query(rson); pushup_2(rt); return ret;}int main() { int p; while(~scanf("%d %d",&n,&m)) { scanf("%s",str+1); S = 0; build(root); while(m--) { scanf("%d",&p); int tmp = update_1(p, root); update_2(p, n, tmp * (-2), root); printf("%d\n",p = (tmp == 1 ? sum[1] : query(root))); update_1(p, root); update_2(p, n, tmp * 2, root); } } return 0;}
1 0
- CSU - 1542 Flipping Parentheses (线段树)
- CSU 1542 Flipping Parentheses(线段树)
- CSU 1542 Flipping Parentheses
- 线段树 csu1542 Flipping Parentheses
- UVALive 6838Flipping Parentheses (线段树)
- Flipping Parentheses (线段树 单点更新 区间查询)
- Flipping Parentheses
- UVALive 6838 Flipping Parentheses // 线段树 区间修改 最值查询
- 2014-2015 ACM-ICPC, Asia Tokyo Regional Contest G題:Flipping Parentheses [线段树]
- UVALive 6838 Flipping Parentheses(线段树、单点更新、区间查询)
- CSU 1110线段树
- Gym 100803G Flipping Parentheses
- Gym 100803G Flipping Parentheses
- CSU 1532: JuQueen(线段树)
- CSU 1098: Happy watering(线段树)
- CSU 1553 线段树+尺取法
- csu 1110 RMQ with Shifts 线段树
- 【CSU 1258 维护序列】+ 线段树
- Google高级搜索技巧
- Right me speak (对我自己说
- 内存对齐规则
- 针对Bug的管理措施
- 浅析startService在一个新进程中启动的流程
- CSU - 1542 Flipping Parentheses (线段树)
- ZOJ 3888 Twelves Monkeys (优先队列+预处理)
- Xcode 6 打包ipa文件
- hdu 1564 博弈
- nginx - 性能优化,突破十万并发
- DNS原理及其解析过程【精彩剖析】
- Javascript 严格模式详解
- java多线程
- (win7 UEFI安装)顺便说说UEFI、GPT和Secure Boot