• ABC160D


    题意:给出 (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]<<'
    ';
    }
    
  • 相关阅读:
    多任务GUI窗口系统(类window,有源码,支持汉字显示、顶层、非矩形和透明窗口)gicell源码
    怎样判断treeview当前节点为treeview显示出来的第一个节点和最后一个节点?
    用 dbgrid 或 dbgrideh 如何让所显示数据自动滚动
    vue路由懒加载及组件懒加载
    vue 中使用rem布局
    纯css实现移动端横向滑动列表&&overflow:atuo;隐藏滚动条
    分布式一致性算法Raft
    HDU_1753 大明A+B
    POJ——3630 Phone List
    HDU_2647 Reward (拓扑排序)
  • 原文地址:https://www.cnblogs.com/Xray-luogu/p/12590123.html
Copyright © 2020-2023  润新知