洛谷1196
- 用标准并查集可以检测两个战舰是否在一列中。
- 一列战舰查找两个战舰中间有几个战舰,可以引入前缀和思想,若知道两个战舰距离队首的距离分别是多少,即可知道其之间距离。
- 问题转化为求任意两战舰距离所在队首距离,引出带权并查集。 d i s [ i ] dis[i] dis[i]表示战舰 i i i距离队首距离, s u m [ i ] sum[i] sum[i]表示战舰 i i i所在队列战舰总数
- d i s [ i ] dis[i] dis[i] 应在递归中修改,即每次合并操作只更改队首,并把两队合并,在下次查询的递归中修改,省去修改的时间复杂度。
int fin(int x)
{
if(fa[x]==x)
return x;
int F=fin(fa[x]);
dis[x]+=dis[fa[x]];
fa[x]=F;
return F;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
for(int i=1;i<=30000;i++)
fa[i]=i,dis[i]=0,sum[i]=1;
cin>>T;
while(T--)
{
char A;
int x,y,xx,yy,ans;
cin>>A>>x>>y;
xx=fin(x);
yy=fin(y);
if(A=='M')
{
fa[xx]=yy;
dis[xx]+=sum[yy];
sum[yy]+=sum[xx];
}
else if(A=='C')
{
if(xx!=yy)
{
cout<<"-1"<<endl;
continue;
}
ans=fabs(dis[x]-dis[y])-1;
cout<<ans<<endl;
}
}
return 0;
}
洛谷 1220
- 区间dp
- 数据范围很小,区间dp够用
- d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] dp[i][j][0/1],分别表示关掉 [ i , j ] [i,j] [i,j]所有路灯后位于 i i i或 j j j所需最小时间。
- d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] dp[i][j][0/1]分别要从 d p [ i + 1 ] [ j ] [ 0 / 1 ] dp[i+1][j][0/1] dp[i+1][j][0/1]和 d p [ i ] [ j − 1 ] [ 0 /