题意:给出 (N,X,Y)。有 (N) 条无向边:
- 对于 (i=1,2,cdots,N-1),连一条从点 (i) 到点 (i+1) 的无向边。
- 连一条从点 (X) 到点 (Y) 的无向边。
对于 (k=1,2,cdots,N-1),要求解决以下问题:
- 找到能使无向边 ((i,j)(1le i<jle N)) 的距离为 (k) 的方案数。
数据范围:
- (3le Nle 2 imes 10^3)
- (1le X,Yle N)
- (X+1<Y)
————————————————————————————————————————————————
Sol:
显然,使用 (O(N^3)) 的 Floyd 算法是不可行的,会直接 TLE。
我们分析一下题目后,会发现:题目中的这个无向图,假如去掉 ((X,Y)) 这条无向边之后,便会成为一条链!
事实上,(O(N^3)) 的 Floyd 算法是一种解决图的多源最短路径的预处理方法。在本题这种情况下,显然有些大材小用了。
我们是否可以找到一种时间复杂度为 (O(N^2)) 的预处理方法呢?答案是肯定的。
设 (s(i,j)) 为点 (i) 到点 (j) 的最短距离。那么枚举 (i,j(1le i<N,i<jle N)),则 (s(i,j)=min{j-i,|X-i|+|Y-j|})。
其中,(j-i) 为不可以经过 ((X,Y)) 的 (i) 到 (j) 的最短距离,(|X-i|+|Y-j|) 为必须经过 ((X,Y)) 的 (i) 到 (j) 的最短距离。
再使用一个桶 (T())。枚举 (i,j(1le i<N,i<jle N)),每次枚举到一组 (i) 和 (j) 后,(T(s(i,j))gets T(s(i,j))+1)。
最终,枚举 (k=1,2,cdots,N-1),每次输出 (T(k)) 即为最终答案。
————————————————————————————————————————————————
Code:
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define iterator IT
#define SIZ(V) V.size()
#define FS(a) fixed<<setprecision(a)
using namespace std;
namespace STARTER {
int MAX(int a,int b) {return a>b?a:b;}
int MIN(int a,int b) {return a<b?a:b;}
int ABS(int a) {return a<0?-a:a;}
int GCD(int a,int b) {return !b?a:GCD(b,a%b);}
int LCM(int a,int b) {return a/GCD(a,b)*b;}
int QSM(int a,int b,int p) {int ret=1;while (b) (b&1)&&(ret=ret*a%p),a=a*a%p,b>>=1;return ret;}
int ROUND(double a) {return a+0.5;}
}
using STARTER::MAX;
using STARTER::MIN;
using STARTER::ABS;
using STARTER::GCD;
using STARTER::LCM;
using STARTER::QSM;
using STARTER::ROUND;
const int maxN=2005;int n,x,y,/*dis[maxN][maxN],*/s[maxN][maxN],ans[maxN],t[maxN*maxN];
int main() {
cin>>n>>x>>y/*,dis[x][y]=1*/;
//for (int i=1;i<n;i++) dis[i][i+1]=1;
//for (int i=1;i<n;i++)
// for (int j=i+1;j<=n;j++) dis[i][j]=1;
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++) //{
//if (i<=x&&j>=y) s[i][j]=x-i+1+j-y;
//else s[i][j]=j-i;
s[i][j]=min(j-i,ABS(x-i)+1+ABS(y-j));
//}
//for (int i=1;i<n;i++) {
// for (int j=i+1;j<=n;j++) printf("s[%d][%d]=%d ",i,j,s[i][j]);
// puts("");
//}
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++) t[s[i][j]]++;
for (int k=1;k<n;k++) cout<<t[k]<<'
';
}