题解:CF524F And Yet Another Bracket Sequence
题解:CF524F And Yet Another Bracket Sequence
题目大意
给你一个括号序列,两种操作,一个是在任意位置插入一种括号,一种是循环移位,求操作完后合法括号序列的最小字典序。
思路
首先括号序列有个很经典的前缀性质,即在前缀中右括号的个数不大于左括号的个数。
然后对于一操作,无疑就是补上不够的括号,因为要字典序最小,所以左括号放最前面,右括号放最后面一定是最优的。
对于操作二直接复制一遍即可。然后对序列跑一遍 SA,从字典序最小的开始跑,如果它的起点小于
这里记
- 如果
cnt < 0 ,那么就要在前面添加左括号,又因为是在最前面添加,所以右括号与左括号的差值最下可以是cnt 。 - 如果
cnt > 0 ,那么就要在最后添加右括号,又因为是在最后面添加,所有与前面的无关,所以右括号与左括号的差值最小为0 ,不然在前面就已经变成不合法序列了。
具体的见代码
Code
#include <bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n;
int tax[N],rak[N];
int sa[N];
int tp[N];
int limit;
int pre[N];
int cnt=0;
string s;
struct node{
int l,r,minn;
}tree[N*4];
namespace Flower{
inline int read(){
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
inline void write(int x){
if (x<0){putchar('-');x=-x;}
if (x>9) write(x/10);
putchar(x%10+'0');
return ;
}
}using namespace Flower;
inline void cardinal_sort(){
for (int i=0;i<=limit;i++)
tax[i]=0;
for (int i=1;i<=n;i++)
tax[rak[i]]++;
for (int i=1;i<=limit;i++)
tax[i]+=tax[i-1];
for (int i=n;i>=1;i--)
sa[tax[rak[tp[i]]]--]=tp[i];
}
inline void suffix_sort(){
limit=128;
for (int i=1;i<=n;i++){
rak[i]=s[i];
tp[i]=i;
}
cardinal_sort();
for (int w=1,p=0;p<n;limit=p,w<<=1){
p=0;
for (int i=1;i<=w;i++)
tp[++p]=n-w+i;
for (int i=1;i<=n;i++)
if (sa[i]>w)
tp[++p]=sa[i]-w;
cardinal_sort();
swap(tp,rak);
rak[sa[1]]=p=1;
for (int i=2;i<=n;i++)
rak[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
}
}
inline void pushup(int now){
tree[now].minn=min(tree[now<<1].minn,tree[now<<1|1].minn);
}
inline void build(int now,int l,int r){
tree[now].l=l;
tree[now].r=r;
tree[now].minn=0x3f3f3f3f;
if (l==r){
tree[now].minn=pre[l];
return ;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
pushup(now);
}
inline int query(int now,int l,int r){
if (tree[now].l>=l&&tree[now].r<=r)
return tree[now].minn;
int res=0x3f3f3f3f;
int mid=(tree[now].l+tree[now].r)>>1;
if (l<=mid)
res=min(res,query(now<<1,l,r));
if (r>mid)
res=min(res,query(now<<1|1,l,r));
return res;
}
int main(){
cin >>s;
for (int i=0;i<(int)s.size();i++){
if (s[i]=='(')
cnt++;
else
cnt--;
}
s+=s;
n=s.size();
s=' '+s;
suffix_sort();
for (int i=1;i<=n;i++)
pre[i]=pre[i-1]+(s[i]=='('?1:-1);
//cout <<"check:: "<<endl;
//for (int i=1;i<=n;i++)
// cout <<pre[i]<<" ";
//cout <<endl;
build(1,1,n);
string ans;
ans.clear();
int m=n/2;
for (int i=1;i<=n;i++){
//cout <<"check:: "<<rak[i]<<endl;
if (sa[i]>m)
continue;
int l=sa[i],r=sa[i]+m-1;
int minx=query(1,l,r);
//cout <<"check:: "<<minx<<" "<<pre[l-1]<<endl;
if ((minx-pre[l-1]<cnt&&cnt<0)||(minx-pre[l-1]<0&&cnt>0))
continue;
if (cnt<0){
int now=l;
while (cnt)
ans+='(',cnt++;
for (int j=1;j<=m;j++)
ans+=s[now++];
}
else{
int now=l;
for (int j=1;j<=m;j++)
ans+=s[now++];
while (cnt)
ans+=')',cnt--;
}
break;
}
cout <<ans<<endl;
return 0;
}
//Love Flower