题解:CF1998D Determine Winning Islands in Race
KarmaticEnding · · 题解
有生之年第一次做到的水 D
我们不考虑 Bessie 怎么赢,反过来,我们来考虑 Elsie 在什么情况下会赢?
首先,如果 Elsie 跟着 Bessie 只走 "main bridge",那么它是没有胜算的,这就是说它需要走一些 alternative bridge。
在什么情况下,Elsie 能通过走 alternative bridge 走到 Bessie 前面呢?这当然需要满足两个条件。
-
Bessie 还没有走过这个 alternative bridge 的起点,也就是说这个起点还没有 Collapse。
-
Bessie 还没有走过这个 alternative bridge 的终点,也就是说这个终点还没有 Collapse。
我们把两个条件同时考虑。
对于每一个岛(以下称作结点)
如果某一时刻 Elsie 走到了 Bessie 前面,说明 Bessie 已经不可能再超过 Elsie 了,那么其它 alternative bridge 就不用了。
反之,如果至始至终 Elsie 都没有走到 Bessie 前面,那么从
那么回到正题,如果 Bessie 的起点在
我们想想怎么统计答案呢?这促使我们思考什么时候 Elsie 会走到 Bessie 前面。假设一个 alternative bridge,其起点为
首先在
其次,我们来想想什么情况下 Elsie 会比 Bessie 快?形象化的理解,当然是 Elsie 到达结点
那么你可以看到,对于每一个 alternative bridge,我们会得到一个区间的始发点
这里有一个我某天突然想到的一个 trick:对于得到的每一个区间,把区间中每一个元素加上
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
int T,n,m;
int d[MAXN],s[MAXN],dis[MAXN];
vector<int> g[MAXN];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<=n;++i){
d[i]=s[i]=0;
g[i].clear();
dis[i]=0x3f3f3f3f;
}
dis[1]=0;
for(int i=0,u,v;i<m;++i){
scanf("%d%d",&u,&v);
g[u].push_back(v);
}
for(int u=1;u<=n;++u){
dis[u]=min(dis[u],dis[u-1]+1);
for(int v:g[u]){
if(v-u>dis[u]+1){
++d[u+1];
--d[v-dis[u]-1];
}
dis[v]=min(dis[v],dis[u]+1);
}
}
for(int i=1;i<=n;++i){
s[i]+=s[i-1]+d[i];
}
for(int i=1;i<n;++i){
if(s[i]){
putchar('0');
}
else{
putchar('1');
}
}
putchar('\n');
}
return 0;
}