「BalkanOI 2018 Day2」Parentrises
「BalkanOI 2018 Day2」Parentrises
part1
显然可以直接贪心。
右括号记-1,左括号记1。
默认起始全部绿色,不染色。
策略如下:
-
从左往右扫,如果右括号个数大于左括号,那么去除目前未被染色的且在最前面的两个右括号(染成红,蓝色)。(如果没有无解)。
-
若此时恰好匹配,有解。
-
若此时左括号多出\(sum\)个,记录上一个括号完全匹配的地方,显然该位置往后是没有点被染色的。从右往左扫到该点,染色\(2*sum\)个点,如果到达某个点时候,左括号在染色后仍旧多于右括号,那么无解。
-
染完色输出即可。
part2
推论:一个括号串能够满足条件当且仅当所有前缀中右括号数量小于等于左括号×2,所有后缀中,左括号个数小于等于右括号数×2。
一段括号串的值为括号的和。
可以记录左括号×2-右括号数\(j\),而 后缀中右括号×2-左括号的最小值 = \(min(总括号值- 某前缀中左括号×2-右括号)\),相当于记录前缀中\(j\)的最大值\(k\)。
那么可以定义出\(dp\)状态\(dp[i][j][k]\),表示当前已经有\(i\)个括号,\(j,k\)如上。
之后转移时保证\(j \geq 0\),对于一个状态,如果它后缀中右括号×2-左括号的最小值 \(\geq 0\),那么计入答案。
转移直接枚举放左括号还是右括号。
复杂度\(o(n^3)\)。
当然由于n比较小,直接打表也行。
#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r){
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
int T;
namespace p_1{
const int mn=1e6+5;
char as[mn];
int sum[mn];
queue<int> had;
int cor[mn],tot[mn];
bool get(int len){
while(!had.empty())had.pop();
rep(q,1,len)cor[q]=0;
int last_zero=0;
rep(q,1,len){
int v=as[q]=='('?1:-1;
if(v==-1)had.push(q);
sum[q]=sum[q-1]+v;
if(sum[q]<0){
sum[q]=0;
if(had.size()<2){
return 0;
}
cor[had.front()]=1;
had.pop();
cor[had.front()]=2;
had.pop();
}
if(sum[q]==0)last_zero=q;
}
if(sum[len]>0){
tot[len+1]=0;
dep(q,len,last_zero+1)tot[q]=tot[q+1]+(as[q]==')');
int td=sum[len]<<1;
dep(q,len,last_zero+1)if(as[q]=='('){
if(td&1)cor[q]=1;
else cor[q]=2;
--td;
if((len-q+1-tot[q] +1)/2>tot[q])return 0;
if(!td)break;
}
return !td;
}
return 1;
}
void solve(){
in(T);
while(T--){
scanf("%s",as+1);
int len=strlen(as+1);
if(get(len)){
rep(q,1,len){
if(cor[q]==0)putchar('G');
else if(cor[q]==1)putchar('B');
else putchar('R');
}
putchar('\n');
}else puts("impossible");
}
}
}
namespace p_2{
int ans[305]={0,0,1,2,2,6,12,18,43,86,148,326,652,1194,2531,5062,9578,19884,39768,76680,157236,314472,613440,1248198,2496396,4906266,9932707,19865414,39237478,79165646,158331292,313801154,631634323,263268639,509707998,43257469,86514938,72895660,288290012,576580024,551498904,962513721,925027435,204521844,634307677,268615347,287719520,559111350,118222693,578936427,105459291,210918582,360752402,920849461,841698915,421349166,985137176,970274345,96196738,666703791,333407575,448451120,71192847,142385694,391328273,82210164,164420328,697441626,75399225,150798450,177655189,77725370,155450740,578770998,806452500,612904993,342317187,437431531,874863062,166780006,649351541,298703075,764861307,105948983,211897966,169754380,332500687,665001374,648783808,296688714,593377428,43060831,684124175,368248343,973819030,849070862,698141717,982308804,88186365,176372730,959772055,320975583,641951166,825442333,311190079,622380158,765671696,14446067,28892134,262223145,966556598,933113189,520941027,287565710,575131420,666019185,263936054,527872108,39283492,877846547,755693087,433079969,737806887,475613767,203965075,701508060,403016113,922600280,277710517,555421034,408729101,377397802,754795604,250532053,528340400,56680793,124734442,232656836,465313672,714603167,631625056,263250105,52648990,389536240,779072480,641256163,302398795,604797590,697370162,632833340,265666673,626109777,298187773,596375546,406717000,515830626,31661245,524137426,667633864,335267721,338047842,390892123,781784246,93415445,65330389,130660778,151215664,822766849,645533691,833650616,380489231,760978462,54775313,491923347,983846694,322809267,940997512,881995017,596258099,507985218,15970429,557503950,859869218,719738429,474482700,767988978,535977949,635491203,387005395,774010790,702061186,253594815,507189630,31838831,822372294,644744581,231777149,215914547,431829094,482869402,576014681,152029355,369499245,244741222,489482444,95772722,952809165,905618323,304323137,304632041,609264082,102336119,335070266,670140532,858231094,960619772,921239537,859847032,56893721,113787442,360033502,982628521,965257035,849451750,439416129,878832258,991939394,464496385,928992770,267785589,802816545,605633083,763528731,474974661,949949322,864267253,946087508,892175009,476000768,273171027,546342054,550581443,469352643,938705286,624000951,673806443,347612879,434823692,233016716,466033432,103642988,440059594,880119188,788176043,40656596,81313192,286602731,202636014,405272028,733717711,472596468,945192936,553096598,892385168,784770329,912447619,707646096,415292185,526477156,861291715,722583423,111861393,588150125,176300243,301383510,244253166,488506332,629844702,421869639,843739278,290375226,384946885,769893770,95673275,473895679,947791358,891751001,164209639,328419278,62075416,175112411,350224822,934621064,806088783,612177559,897003764,948394637,896789267,953901352,418921686,837843372};
int dp[2][305][605];
const int mod=1e9+7;
void add(int &a,int b){
a=(a+b)%mod;
}
void calc(){
int ed=300;
dp[0][0][0]=1;
bool ok=0;
rep(q,0,ed){
ok=!ok;
mem(dp[ok],0);
rep(l,0,q){
int r=q-l;
rep(w,0,2*q){
if(r*2-l -w>=0)add(ans[q],dp[!ok][l][w]);
if(l*2-r-1>=0)add(dp[ok][l][max(w,(r+1)*2-l)],dp[!ok][l][w]);
add(dp[ok][l+1][max(w,r*2-l-1)],dp[!ok][l][w]);
}
}
}
}
void solve(){
in(T);
int n;
while(T--){
in(n);
printf("%d\n",ans[n]);
}
}
}
int main(){
freopen("parentrises.in","r",stdin);
freopen("parentrises.out","w",stdout);
int P;
in(P);
if(P==1)p_1::solve();
else p_2::solve();
return 0;
}