[CF1149C](ツリージェネレータ)

  • 問題の意味

括弧内に与えられたツリー配列、M動作、2つのブラケット各交換、交換順序は、各演算出力の後の括弧内に依然として有効であることを確認する(オペレーションが含まれていない)ツリーの直径があります

  • 解決

一致が、その後の括弧内の数字は、残りの要求の所望の直径であることを特徴と最初の変換の問題、ブラケットのツリー配列、我々はいくつかのサブストリングが消去後ほとんど残存ブラケット括弧を満たす見つける

ような配列ツリーブラケットこれは、()(())を除去)((、残りの3つのブラケット一致括弧を消去し、必要な直径であります

しかし、これはまだにゃが行われていないので、1帝国の我々の再変換値は括弧を左に右括弧が-1で、問題は、事前にデジタルとデジタルの期間の後で最大のいくつかを軽減するように、隣接する2見つけることになり違いが答えです

ここでは、このタイトルのカットと考えることができます

そこで問題は、そうするように形質転換されている、との問題の範囲のために修理する+ +範囲に関連するいくつかの値を維持し、我々は(この単純なツリーラインを使用することができますヘビー秘密)データ構造

各セグメントツリーノード、我々保守/リア最小/最大値は、間隔と、すべての答えの前及び/接尾辞D値の前に間隔Dの最大値は

Dそれは何値はありますか?私たちは、単純に半分にした後、指定された間隔内に線を引くと、前半と最大をカットする、違いは、Dの値がこの範囲であります

  • コード

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ls (x<<1)
#define  rs (x<<1|1)
#define mid ((l+r)>>1)
#define N 200000
using namespace std;
struct zero{
int sum,prex,prem,sucx,sucm,pred,sucd,d,ans;
zero(){}
zero(int p1,int p2,int p3,int p4,int p5,int p6,int p7,int p8,int p9){sum=p1,prex=p2,prem=p3,sucx=p4,sucm=p5,pred=p6,sucd=p7,d=p8,ans=p9;}
}tree[N<<2];
// sum:区间和
// ans:区间答案
// pre/suc-x/m 区间 前/后 缀最 大/小 值
// pre/suc-d 前/后 缀 D值
// d 区间D 值 
const zero L=zero(1,1,0,1,0,1,1,1,1);
const zero R=zero(-1,0,-1,0,-1,1,1,1,1);
char input[N];
zero operator +(const zero &a,const zero &b){
    zero c;
    c.prex=max(a.prex,a.sum+b.prex);
    c.sucx=max(b.sucx,a.sucx+b.sum);
    c.prem=min(a.prem,a.sum+b.prem);
    c.sucm=min(b.sucm,a.sucm+b.sum);
    c.d=max(b.d-a.sum,a.d+b.sum);
    c.pred=max(a.pred,max(b.pred-a.sum,a.d+b.prex));
    c.sucd=max(b.sucd,max(b.sum+a.sucd,b.d-a.sucm));
    c.sum=a.sum+b.sum;
    c.ans=max(max(a.ans,b.ans),max(b.pred-a.sucm,a.sucd+b.prex));
    return c;
}
void build(int x,int l,int r){
    if(l==r){if(input[l]=='(')tree[x]=L;else tree[x]=R;return;}
    build(ls,l,mid),build(rs,mid+1,r);
    tree[x]=tree[ls]+tree[rs];
}
void update(int x,int l,int r,int pos){
    if(l==r){if(input[l]=='(')tree[x]=L;else tree[x]=R;return;}
    if(pos<=mid)update(ls,l,mid,pos);else update(rs,mid+1,r,pos);
    tree[x]=tree[ls]+tree[rs];
}
int n,m;
int main(){
    scanf("%d%d",&n,&m);n=(n-1)*2;
    scanf("%s",input+1);
    build(1,1,n);
    printf("%d\n",tree[1].ans);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        swap(input[a],input[b]);
        update(1,1,n,a),update(1,1,n,b);
        printf("%d\n",tree[1].ans);
    }
}

おすすめ

転載: www.cnblogs.com/stepsys/p/11580917.html