#603(div 2)
603(div 2)
E .Editor
-
题意: 输入一串字符串,由
(
,)
,L
,R
和其他字符组成。 -
分析:
- 首先要知道这几点,( 一 )对于括号匹配问题我们一般让左括号表示\(+1\) ,右括号表示\(-1\) 。这样如果前缀和为0表示左右括号都合理的匹配了。( 二 ) 跟据题意最后左右括号的最大嵌套数是所需的颜色数,由于从左向右先遇到左括号,一直+1.所以前缀和最大值为所需的颜色数。
- 什么时候是 “ 很好 ” 的匹配?应该是所有的左右括号都有匹配,即任何一个前缀和都大于等与0,也就是 前缀和的最小值为0 。同时为了保证所有左右括号都匹配了,要求 第n个前缀和为0。 此时我们输出的结果是 前缀和最大值 。 不满足括号全部匹配就输出-1。
- 那么由于在遍历字符串指行各种指令时会修改位置各个值,即动态修改然后问你结果。这就要用数据结构——线段树。本题需要维护三个值即上面加粗的三个值。
- 这道题其实很好的作为线段树模板题。体现了线段数维护动态修改时的作用。很快会写一个关于线段树的博客。
-
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MA=1e6+5; const int INF=0x3f3f3f3f; struct node { int l,r; int sum; int mx; int mn; int add; }tree[MA*4+5]; void Pushup(int index) { tree[index].sum=tree[index<<1].sum+tree[index<<1|1].sum; tree[index].mx=max(tree[index<<1].mx,tree[index<<1|1].mx); tree[index].mn=min(tree[index<<1].mn,tree[index<<1|1].mn); } void Pushdown(int index) { if(tree[index].add){ tree[index<<1].sum+=(tree[index<<1].r-tree[index<<1].l+1)*tree[index].add; tree[index<<1|1].sum+=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add; tree[index<<1].mx+=tree[index].add; tree[index<<1|1].mx+=tree[index].add; tree[index<<1].mn+=tree[index].add; tree[index<<1|1].mn+=tree[index].add; tree[index<<1].add+=tree[index].add; tree[index<<1|1].add+=tree[index].add; tree[index].add=0; } } void Build(int l,int r,int index) { tree[index].l=l; tree[index].r=r; tree[index].add=0; if(l==r){ scanf("%d",&tree[index].sum); tree[index].mx=tree[index].mn=tree[index].sum; return ; } int mid=(l+r)>>1; Build(l,mid,index<<1); Build(mid+1,r,index<<1|1); Pushup(index); } void Updata(int l,int r,int index,int val) { if(l<=tree[index].l&&tree[index].r<=r){ tree[index].sum+=(tree[index].r-tree[index].l+1)*val; tree[index].mx+=val; tree[index].mn+=val; tree[index].add+=val; return ; } Pushdown(index); int mid=(tree[index].l+tree[index].r)>>1; if(l<=mid) Updata(l,r,index<<1,val); if(mid<r) Updata(l,r,index<<1|1,val); Pushup(index); } int querySum(int l,int r,int index) { if(l<=tree[index].l&&tree[index].r<=r){ return tree[index].sum; } Pushdown(index); int Sum=0; int Max=0; int Min=INF; int mid=(tree[index].l+tree[index].r)>>1; if(l<=mid) Sum+=querySum(l,r,index<<1); if(mid<r) Sum+=querySum(l,r,index<<1|1); return Sum; } int queryMx(int l,int r,int index) { if(l<=tree[index].l&&tree[index].r<=r){ return tree[index].mx; } Pushdown(index); int Sum=0; int Max=0; int Min=INF; int mid=(tree[index].l+tree[index].r)>>1; if(l<=mid) Max=max(Max,queryMx(l,r,index<<1)); if(mid<r) Max=max(Max,queryMx(l,r,index<<1|1)); return Max; } int queryMn(int l,int r,int index) { if(l<=tree[index].l&&tree[index].r<=r){ return tree[index].mn; } Pushdown(index); int Sum=0; int Max=0; int Min=INF; int mid=(tree[index].l+tree[index].r)>>1; if(l<=mid) Min=min(Min,queryMn(l,r,index<<1)); if(mid<r) Min=min(Min,queryMn(l,r,index<<1|1)); return Min; } string s; int ss[MA]; int main() { int n; scanf("%d",&n); n=n+5; Build(1,n,1); cin>>s; int pos=1; vector<int>ans; for(int i=0;i<s.size();++i){ if(s[i]=='('){ Updata(pos,n,1,1-ss[pos]); ss[pos]=1; } else if(s[i]==')'){ Updata(pos,n,1,-1-ss[pos]); ss[pos]=-1; } else if(s[i]=='L'){ if(pos>1) pos--; } else if(s[i]=='R'){ pos++; } else{ if(ss[pos]==1){ Updata(pos,n,1,-1); } else if(ss[pos]==-1){ Updata(pos,n,1,1); } ss[pos]=0; } if(queryMn(1,n,1)==0&&querySum(n,n,1)==0){ ans.push_back(queryMx(1,n,1)); } else ans.push_back(-1); } for(int i=0;i<ans.size();++i){ printf("%d ",ans[i]); } printf("\n"); return 0; }