1. 程式人生 > >CodeForces - 524F And Yet Another Bracket Sequence

CodeForces - 524F And Yet Another Bracket Sequence

|| blank int 自動 要求 += com .... %s

題面在這裏!

(會考完之後休閑休閑2333)

可以發現,如果把一個串中"()"自動刪除,最後剩的一定是形如"))))....))(((..((("這樣的串,然後我們多加進去的括號的個數就是剩的這個串的長度。。

然鵝這個題首先要求的是最後總長度最小,並且我們可以觀察發現把最後一個循環位移到最前面是會使一對")("相抵消的。

所以我們最後的最優答案一定是排除已經匹配的括號之後只剩一種括號的串,我們枚舉一下循環位移了多少(循環位移之後一定是一個原串的後綴+前綴的形式),然後再判斷一下這種循環位移是否會只剩一種串(可以把原串中 ‘(‘個數 - ‘)‘個數 分類討論一下,然後退出一個形如 一個區間裏的前綴/後綴 都要 大於等於 某個前綴/後綴 的式子,可以 O(N) 單調隊列掃一遍 ),然後用hash直接更新答案即可,顯然最後多的括號都堆在前面或者後面是最優的,然後就做完了2333

(最近常數是真的小啊2333)

技術分享圖片

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2000005,ha=1e9+9;

inline int Get(char x){ return x==‘(‘?1:-1;}

inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}

int n,q[maxn],hd,tl,a[maxn],tot,p,N;
int c[maxn],h[maxn];
char s[maxn]; 

inline int gethash(int x,int len){ return add(h[x+len-1],ha-h[x-1]*(ll)c[len]%ha);}

inline bool cmp(int x,int y){
	int l=0,r=n,mid,an=0;
	while(l<=r){
		mid=l+r>>1;
		if(gethash(x,mid)==gethash(y,mid)) an=mid,l=mid+1;
		else r=mid-1;
	}
	
	return an==n?1:s[x+an]==‘(‘;
}

inline void update(int x){ if(!p||cmp(x,p)) p=x;}

inline void solve1(){
	c[0]=1;
	for(int i=1;i<=N;i++){
	    a[i]=a[i-1]+Get(s[i]);
	    c[i]=add(c[i-1],add(c[i-1],c[i-1]));
	    h[i]=add(add(h[i-1],add(h[i-1],h[i-1])),(s[i]==‘(‘?1:2));
	}
	
	hd=1,tl=0;
	for(int i=1;i<N;i++){
		while(hd<=tl&&a[i]<=a[q[tl]]) tl--;
		q[++tl]=i;
		while(hd<=tl&&q[hd]+n<=i) hd++;
		
		if(i>=n&&a[q[hd]]>=a[i-n]) update(i-n+1);
	}
	
	for(int i=0;i<n;i++) putchar(s[p+i]);
	for(int i=1;i<=tot;i++) putchar(‘)‘);
}

inline void solve2(){
	c[0]=1;
	for(int i=1;i<=N;i++){
	    c[i]=add(c[i-1],add(c[i-1],c[i-1]));
	    h[i]=add(add(h[i-1],add(h[i-1],h[i-1])),(s[i]==‘(‘?1:2));
	}
	
	for(int i=N;i;i--) a[i]=a[i+1]-Get(s[i]);
	
	hd=1,tl=0;
	for(int i=N-1;i;i--){
		while(hd<=tl&&a[i]<=a[q[tl]]) tl--;
		q[++tl]=i;
		while(hd<=tl&&q[hd]-n>=i) hd++;
		
		if(i<=n&&a[q[hd]]>=a[i+n]) update(i);
	}
	
	for(int i=tot;i<0;i++) putchar(‘(‘);
	for(int i=0;i<n;i++) putchar(s[p+i]);
}

int main(){
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	
	scanf("%s",s+1),n=strlen(s+1),N=n<<1;
	for(int i=1;i<=n;i++) s[i+n]=s[i],tot+=Get(s[i]);
	
	if(tot>=0) solve1();
	else solve2();
	
	return 0;
}

  

CodeForces - 524F And Yet Another Bracket Sequence