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;
}