给你一个整数 n
和一个二维整数数组 queries
。
有 n
个城市,编号从 0
到 n - 1
。初始时,每个城市 i
都有一条单向道路通往城市 i + 1
( 0 <= i < n - 1
)。
queries[i] = [ui, vi]
表示新建一条从城市 ui
到城市 vi
的单向道路。每次查询后,你需要找到从城市 0
到城市 n - 1
的最短路径的长度。
所有查询中不会存在两个查询都满足 queries[i][0] < queries[j][0] < queries[i][1] < queries[j][1]
。
返回一个数组 answer
,对于范围 [0, queries.length - 1]
中的每个 i
,answer[i]
是处理完前 i + 1
个查询后,从城市 0
到城市 n - 1
的最短路径的长度
思路:
开始考虑的是二分搜索,因为觉得既然有l到r的边,那么就不用考虑l到(l+1,,,,r-1)之间的
边了,但是这里会发现无法判定当没有从l到(l+r)/2的边时候该怎么走,因为虽然题目要求不能有相交的边,但是可以有从一个边为左端点,然后右端点不同的情况。最终发现利用二分无法很好的解决这个问题。
本题考虑的是并查集的思路,将关注的重点放在边上,起初的时候每个节点i,f[i]+1表示其所能指向的最远的边,然后考虑的是从0到n-1一共有多少条边就行,每当遇到一个从l到r的边,就把从l+1开始到r-2的点都合并到r上,(r-1因为本来就有到r的边所以不用合并),每次合并都使得边的数目减少一,所以只需要记录一下边减少的数目,在和边原本的数目相减就是加上一条边以后最短距离了。
class Solution {
public:
vector<int>f;
vector<int> shortestDistanceAfterQueries(int n, vector<vector<int>>& queries) {
f.resize(n);
for(int i=0;i<n;i++)
f[i]=i;
vector<int>ans;
int cnt=n-1;
for(auto e:queries)
{
int x=e[0],y=e[1]-1;
int r=find(y);
for(int i=find(x);i<y;i=find(i+1))
{
f[i]=r;
cnt--;
}
ans.push_back(cnt);
}
return ans;
}
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
};