一道需要发现一些简单的性质的中档题(不过可能这道题放在省选 D1T3 中偏简单了?)
u1s1 现在已经是 (1 ext{s}) (10^9) 的时代了吗?落伍了落伍了/ll
首先我们考虑 (f(i,G)) 是个什么东西,显然对于 (x>i) 的 (x) 肯定就不可能有贡献了对吧,因为扫描到 (x) 时 (i) 已经从图中删去了,而扫描到 (i) 时答案肯定会有 (1) 的贡献,因此我们不妨先给所有 (h(G_i)) 都加上 (n),然后只考虑 (x<i) 的 (x) 的贡献即可。思考什么情况下当我们删到 (x) 时 (x o i) 和 (i o x) 都存在,经过一番观察可以发现以下性质:
Observation. 删到 (x) 时 (x o i) 和 (i o x) 的路径都存在,当且仅当存在 (x o i) 和 (i o x) 的路径只经过编号 (ge x) 的点。
证明:充分性显然。必要性等价于如果不存在 (x o i) 或 (i o x) 的路径只经过编号 (ge x) 的点,那么必然删到 (x) 时 (x o i) 和 (i o x) 中的一者不存在。考虑数学归纳,假设命题对 (x'le x) 均成立,那么从 (x-1) 推到 (x) 时我们采取反证法,假设 (x o i) 和 (i o x) 二者在考虑到 (x) 时都存在,但是不存在 (x o i) 和 (i o x) 的路径只经过编号 (ge x) 的点,那么你任取一对此时没有被删掉的 (x o i) 和 (i o x) 的路径,它们路径上编号最小的点必然是 (<x) 的,我们假设这个点为 (y),那么显然存在 (y o x,x o y) 的路径,而由于 (y) 是 (x o i) 和 (i o x) 路径上编号最小的点,(y o x) 和 (x o y) 路径上点的编号必然都 (>y),有归纳假设 (y) 此时肯定已经被删除了,矛盾。
有了这个性质之后解题就异常方便了,我们考虑预处理出 (g_{x,y}) 表示在所有 (x o y) 的满足不经过编号 (<min(x,y)) 的点的路径中,经过的边的编号的最小值最大是多少,那么不难发现对于一对点 ((x,y)(x<y)) 而言,它只可能对满足 (ilemin(g_{x,y},g_{y,x})) 的 (h(G_i)) 产生 (1) 的贡献,差分一下转化为后缀和即可。那么怎么求 (g_{x,y}) 呢?我们考虑从大到小枚举中转点 (zgemin(x,y)),用类似于 Floyd 的方式,取 (min(g_{x,z},g_{z,y})) 更新答案即可。
时间复杂度 (mathcal O(n^3+m)),略微有点卡常。
const int MAXN=1000;
const int MAXM=2e5;
const int INF=0x3f3f3f3f;
int n,m,mx[MAXN+5][MAXN+5],c[MAXM+5];
int main(){
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),chkmax(mx[u][v],i);
for(int i=1;i<=n;i++) mx[i][i]=INF;
for(int k=n;k;k--) for(int i=1;i<=n;i++) for(int j=1;j<=((i<=k)?n:k);j++)
chkmax(mx[i][j],min(mx[i][k],mx[k][j]));
// for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) printf("%d%c",mx[i][j],"
"[j==n]);
for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) c[min(mx[i][j],mx[j][i])]++;
c[m+1]=n;for(int i=m+1;i;i--) c[i-1]+=c[i];
for(int i=1;i<=m+1;i++) printf("%d%c",c[i],"
"[i==m+1]);
return 0;
}