E.エディタ
テキストエディタの開発は難しい問題です。テキストに着色括弧のための余分なモジュールを実装する必要があります。
あなたのエディタは、現在の文字を指し無限の長さやカーソルでの行で構成されています。それは(文字のペアの間ではなく)文字のみの1を指していることに注意してください。したがって、インデックス文字を指しています。ユーザーは、カーソルを左右1点の位置を移動することができます。カーソルが最初(左端)位置にすでにある場合、それは左に移動しません。
最初に、カーソルが最初(左端)の文字です。
また、ユーザは、カーソルが現在で指している位置に文字またはブラケットを(いずれか(または))書き込むことができます。新キャラクターは、常にその位置の古い値を上書きします。
あなたのエディタは、現在の行が正しいテキストであるかどうか、確認する必要があります。それらの括弧が正しいブラケットシーケンスを形成している場合、テキストは正しいです。
正式には、正しいテキスト(CT)は、次の規則を満たしている必要があります。
括弧なしの任意の行は、CT(行は空白を含めることができる)です。
文字列の最初の文字が場合-である(最後の-である)、およびすべての残りの部分の形CT、その後、全体のラインはCTです。
2連続書かれたCTもCTです。
正しい文章の例:こんにちは(codeforces)、ラウンド、((I)(ライト))EDI(TOR)S、(私)。間違ったテキストの例:こんにちは)おっと()、ラウンド、((私)。
ユーザーがエディタで動作するように特殊なコマンドを使用しています。各コマンドは、このコマンドを実行するために書かれなければならないそのシンボルを、持っています。
次のようにコマンドと文字の対応は次のとおりです。
L - (それはすでに最初の文字を指している場合場所に遺骨を)カーソルを1文字左に移動させます。
R -カーソルを1文字右に移動させます。
任意の小文字のラテン文字またはブラケット((または)) -カーソルが今の位置に入力された文字を書き込みます。
完全に理解するために、最初の例と以下のノートで、そのイラストを見てみましょう。
あなたは、ユーザーが入力した文字を含む文字列を与えられています。モジュールの仕事を着色ブラケットについては、各コマンドの後に以下を行う必要があります。
エディタ内の現在のテキストが正しいテキストであるかどうかをチェック。
そうである場合、全てのブラケットを着色するために、必要な色の最小数を印刷します。
ブラケットの2対(第二の又はその逆の最初の)ネストされている場合は、ブラケットのこれらの対は、異なる色で塗装されるべきです。ブラケットの2組がネストされていない場合は、それらは異なるまたは同じ色で塗装することができます。例えば、ブラケットシーケンスの()(())()()の各色の最小数は2であり、そしてブラケット配列について(()(()())())(()) - 3です。
各コマンドを処理した後の色の最小数を出力するプログラムを書きます。
入力
コマンドの数 - 最初の行は、整数n(1≤n≤106)を含みます。
2行目は、Sが含まれている - 一連のコマンドを。文字列sは、n個の文字で構成されています。文字列内のすべての文字が有効なコマンドであることを保証されています。
出力
単一ラインプリントnは整数で、ここで、i番目の数です。
-1最初のiコマンドを処理した後に受信したラインが有効なテキストでない場合
、正しいテキストの場合には色の最小数。
例
入力
11
(RaRbR)L)L(
出力
-1 -1 -1 -1 -1 -1 1 1 -1 -1 2
入力
11
(R)R(R)Ra)がC
出力
-1 -1 1 1 -1 -1 1 1 1 -1 1
注意
最初の例では、エディタ内のテキストは次の形式をとります。
(
^
(
^
(
^
(
^
(AB
^
(AB
^
(AB)
^
(AB)
^
())
^
())
^
(())
^
問題の意味
長いタイトルに直面している、が、1つは、ノートの読み取りを見ることができます。
あなたのエディタを付け、LRは左、左と右のカーソルの動きを表し、右括弧を小文字、それは括弧と文字の周りにカーソルの位置を変更すると述べました。(あなたは遠い今残っている場合は、左に移動することはできません)
あなたは、法的な括弧列かどうかを判断できるように、n個の操作を与えられている場合は、ネストされた括弧、そうでない場合は、出力の法的最大出力数-1
問題の解決策
問題の動画を解決https://www.bilibili.com/video/av77514280/
(1)されていると-1
私たちは、プレフィックスとメンテナンス、法的およびブラケットシーケンスは全て0であり、接頭辞と最小値は0以上です。この条件が満たされた場合には、ネストされた括弧や接頭辞の私の最大数が最大です。
これは実際にツリーラインで行うことができます
コード
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+107;
#define inf 0x3f3f3f3f
struct node{
int l,r;//区间[l,r]
int add;//区间的延时标记
int sum;//区间和
int mx; //区间最大值
int mn; //区间最小值
}tree[maxn*4+5];//一定要开到4倍多的空间
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;//刚开始一定要清0
if(l == r){
scanf("%d",&tree[index].sum);
tree[index].mn = tree[index].mx = 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 && r >= tree[index].r){
/*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
个数,所以区间和 以及 最值为:
*/
/*tree[index].sum = (tree[index].r-tree[index].l+1)*val;
tree[index].mn = val;
tree[index].mx = val;
tree[index].add = val;//延时标记*/
//在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1
//个数,所以区间和 以及 最值为:
tree[index].sum += (tree[index].r-tree[index].l+1)*val;
tree[index].mn += val;
tree[index].mx += 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(r > mid){
updata(l,r,index<<1|1,val);
}
pushup(index);
}
int querySum(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].sum;
//return tree[index].mn;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
ans += querySum(l,r,index<<1);
}
if(r > mid){
ans += querySum(l,r,index<<1|1);
}
return ans;
}
int queryMi(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].mn;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
Min = min(queryMi(l,r,index<<1),Min);
}
if(r > mid){
Min = min(queryMi(l,r,index<<1|1),Min);
}
return Min;
}
int queryMx(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].mx;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
Max = max(queryMx(l,r,index<<1),Max);
}
if(r > mid){
Max = max(queryMx(l,r,index<<1|1),Max);
}
//return ans;
return Max;
//return Min;
}
string s;
int ss[maxn];
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--;
//pos=max(pos,1);
}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(queryMi(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++){
cout<<ans[i]<<" ";
}
cout<<endl;
}