E. Nearest Opposite Parity(最短路)
n(n<=2e5)個數的數組a[],第i個數可以跳到i-a[i]或i+a[i],
若a[i]跳到一個與其奇偶性不同的a[j]即可認爲對於i來說跳躍終止。
對於每個i,求最短的跳躍終止的距離。
建反圖,i-a[i]連向i代價1,i+a[i]連向i代價1,所有偶點連超級偶點代價0,所有奇點連超級奇點代價0
這樣本來所有奇點到超級偶點的最短路,可認爲是超級偶點到所有奇點的最短路
同理,跑一次超級奇點到所有偶點的最短路,粘一下dij板子就過了
dfs由於有環的更新順序故不可行,也可以不實際建出超級源點,
考慮多源bfs,補一下多源bfs的做法,感覺很簡潔
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,a[N],dis[N],ans[N];
vector<int>e[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
if(i-a[i]>=1)e[i-a[i]].push_back(i);
if(i+a[i]<=n)e[i+a[i]].push_back(i);
}
for(int d=0;d<2;++d)
{
memset(dis,-1,sizeof dis);
queue<int>q;
for(int i=1;i<=n;++i)
{
if((a[i]&1)==d)
{
dis[i]=0;
q.push(i);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int v:e[u])
{
if(dis[v]==-1)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
for(int i=1;i<=n;++i)
{
if((a[i]&1)!=d)
{
ans[i]=dis[i];
}
}
}
for(int i=1;i<=n;++i)
printf("%d%c",ans[i]," \n"[i==n]);
return 0;
}
F. Two Bracket Sequences(bfs+dp)
給你兩個不超過200的不一定合法的括號序列
輸出一個最短的合法的括號串,使得這兩個括號序列都是這個串的子序列
子序列匹配顯然越前出現越好,所以dp2選1去枚舉當前選左括號還是選右括號,貪心地和當前位置對應匹配
dp[i][j][k]代表當前該匹配s的第i個字母 該匹配t的第j個字母 且有k個左括號未匹配(左括號比右括號多k個)
狀態數降到200*200*400,pre[i][j][k]直接暴力記錄前驅是哪個三元組即可,空間足夠
最後答案即爲dp[n][m][0]的值,然後根據前驅倒序輸出路徑
#include<bits/stdc++.h>
using namespace std;
const int N=205,M=405;
int n,m,d[N][N][M],cnt;
char s[N],t[N],res[M];
struct pos
{
int x,y,z;
}pre[N][N][M],now,las;
void solve()
{
int x,y,z,xx,yy,zz;
memset(d,-1,sizeof d);
queue<pos>q;
q.push({0,0,0});
d[0][0][0]=0;
while(!q.empty())
{
now=q.front();
q.pop();
x=now.x,y=now.y,z=now.z;
for(char c:{'(',')'})
{
xx=x,yy=y,zz=z;
if(xx<n&&s[xx]==c)xx++;
if(yy<m&&t[yy]==c)yy++;
if(c=='(')zz++;
else zz--;
if(zz<0||zz>=M)continue;
if(d[xx][yy][zz]==-1)
{
d[xx][yy][zz]=d[x][y][z]+1;
pre[xx][yy][zz]={x,y,z};
if(xx==n&&yy==m&&zz==0)
{
las={xx,yy,zz};
return;
}
q.push({xx,yy,zz});
}
}
}
}
int main()
{
scanf("%s%s",s,t);
n=strlen(s);m=strlen(t);
solve();
int x,y,z;
while(1)
{
now=las;
x=now.x,y=now.y,z=now.z;
if(x+y+z==0)break;
if(pre[x][y][z].z<z)res[cnt++]='(';
else res[cnt++]=')';
las=pre[x][y][z];
}
reverse(res,res+cnt);
res[cnt++]='\0';
printf("%s\n",res);
return 0;
}