Gym 100803G Flipping Parentheses

来源:互联网 发布:aws centos root 编辑:程序博客网 时间:2024/05/22 07:02

题意:就是给你一个匹配好的括号串长度为n,在给你m个操作,每个操作就给翻转摸一个位置的括号,对于每一个操作,你要找到一括号将其翻转,使得最后这个串还是匹配的,若存在多个解,翻转最左边的那个括号。


思路:如果操作是翻转有某个括号,那么我们一定的翻转与之相反的而一个括号。

把左括号转化为1,有括号转化为-1,用线段树来维护前缀和;
因为若一个完全匹配的括号串,他的每一个位置的前缀和一定是大于等于0的;
当操作将在i位置右括号翻转,那么i位置以后的所有前缀和都加2;
我们要是的这个达到平衡,于是就去寻找一个左括号翻转,使得其后面的前缀和都减二,最终达到平衡。
对于这个左括号怎么找?我们可用二分,因为操作之影响i位置以后的前缀和,i之前的是不会改变的;
因此我们只要找到一段区间,这段区间内每一个数都大于等于二。

当操作将左括号翻转的时候,和上面的思路一样,但是这个时候你只要在这个i位置之前找一个最左边的左括号j就可以了;
为什么?因为把这个左括号j翻转(j在i前面),j之后的都加上2,这样是不是保证后面一定是每一个前缀和都是大于等于0的。
于是我们要去寻找一个最左边的括号。这个相对比较简单,可以直接用set来维护。


#include<stdio.h>#include<string.h>#include<algorithm>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#include<iostream>#include<stdlib.h>#include<set>#include<map>#include<queue>#include<stack>#include<vector>#include<bitset>#pragma comment(linker, "/STACK:1024000000,1024000000")template <class T>bool scanff(T &ret){    char c; int sgn; T bit=0.1;    if(c=getchar(),c==EOF) return 0;    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();    sgn=(c=='-')?-1:1;    ret=(c=='-')?0:(c-'0');    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');    if(c==' '||c=='\n'){ ret*=sgn; return 1; }    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;    ret*=sgn;    return 1;}#define inf 1073741824#define llinf 4611686018285162540LL#define eps 1e-8#define mod 9223372034707292160LL#define pi acos(-1.0)#define lth (th<<1)#define rth (th<<1|1)#define rep(i,a,b) for(int i=a;i<=b;i++)#define drep(i,a,b) for(int i=a;i>=b;i--)#define mset(x,val) memset(x,val,sizeof(x))#define mcpy(x,y) memcpy(x,y,sizeof(y))#define findx(x) lower_bound(b+1,b+1+bn,x)-b#define mpii(a,b) make_pair(a,b);#define NN 101010#define MM 202020using namespace std;typedef long long ll;typedef long double lb;typedef pair<int,int> pii;struct node{    int l,r,val,add;}t[NN*20];int n,m,h;int a[NN*10],b[NN*10];char s[NN*10];int ql,qr,qv,qmi;set<int>st;void built(){    for(h=1;h<n+3;h<<=1);    rep(i,0,h<<1) t[i].val=t[i].add=0;    rep(i,1,n) t[i+h].val=b[i];    rep(i,0,h-1) t[i+h].l=t[i+h].r=i;    drep(th,h-1,1){        t[th].l=t[lth].l;        t[th].r=t[rth].r;        t[th].val=min(t[lth].val,t[rth].val);    }}void maintain(int th,int l,int r){    if(r>l){        t[th].val=min(t[lth].val,t[rth].val);        t[th].val+=t[th].add;    }    else{        t[th].val+=t[th].add;        t[th].add=0;    }}void update(int th,int l,int r){    if(ql<=l&&qr>=r){        t[th].add+=qv;    }    else{        int mid=(r+l)>>1;        if(ql<=mid) update(lth,l,mid);        if(qr>mid)  update(rth,mid+1,r);    }    maintain(th,l,r);}void query(int th,int l,int r,int add){    if(ql<=l&&qr>=r){        qmi=min(qmi,t[th].val+add);    }    else{        int mid=(r+l)>>1;        if(ql<=mid) query(lth,l,mid,t[th].add+add);        if(qr>mid)  query(rth,mid+1,r,t[th].add+add);    }}void add(int pos){    a[pos]=-1;    st.insert(pos);    ql=pos;    qr=n;    qv=-2;    update(1,0,h-1);}void dlt(int pos){    a[pos]=1;    st.erase(pos);    ql=pos;    qr=n;    qv=2;    update(1,0,h-1);}int main(){    scanf("%d%d",&n,&m);    scanf("%s",s+1);    b[0]=0;    rep(i,1,n){        if(s[i]=='(') a[i]=1;        if(s[i]==')') a[i]=-1,st.insert(i);        b[i]=b[i-1]+a[i];    }    built();    int ans;    rep(i,1,m){        int pos;        scanf("%d",&pos);        if(a[pos]==1){            add(pos);            ans=*st.begin();            dlt(ans);        }        else{            dlt(pos);            int l,r;            l=1,r=n;            while(l<=r){                ql=(l+r)>>1;                qr=n;                qmi=inf;                query(1,0,h-1,t[1].add);                if(qmi>=2) r=ql-1;                else l=ql+1;            }            ans=l;            add(ans);        }        printf("%d\n",ans);    }    return 0;}



0 0
原创粉丝点击