题解:【MX-X27-T3】Sakura

题目传送门

题意分析

记原题面中 \(H\)\(h\)

首先发现花与花之间没有区别,我们在意的是 \(v_i\)。下文以 \(v_i\) 同时代表一朵花。

为了字典序最大,钦定 \(v_1\geq v_2\geq\cdots\geq v_n\)

可以发现,速度越大的花,下降得越快废话,因此对于同一个高度来说,速度大的花会先到达。

因而第 \(i\)\(b_j=k\)\(v_i\) 的。

\(\textit{id}_i\) 表示 \(b_i\)\(v_{\textit{id}_i}\) 的,这可以很容易地求出来。

\(\textit{last}\) 表示 \(b_i\) 左边的最后一个 \(v_1\) 的高度。\(v_1\) 到达 \(\textit{last}\) 的时间小于等于 \(v_{\textit{id}_i}\) 到达 \(b_i\) 的时间,有:

\[\begin{aligned} \dfrac{h-\textit{last}}{v_1}&\leq\dfrac{h-b_i}{v_{\textit{id}_i}} \\ v_{\textit{id}_i}&\leq \dfrac{h-b_i}{h-\textit{last}}v_1 \end{aligned} \]

但是这个条件是充分的,有没有可能不取等,从而使 \(v_1\) 更大,从而更优呢?实际上是不存在的。

假设 \(v_1\) 已知。对于 \(v_2\)\(v_2\) 要尽可能大才能满足字典序最大,所以报告高度的时间会和前面 \(v_1\) 报告高度的时间相同,即取到 \(\dfrac{h-\textit{last}}{v_1}=\dfrac{h-b_i}{v_2}\)

推广到 \(v_3,v_4,\cdots,v_n\)\(v_i\) 与前面最近的 \(v_{i-1}\) 报告高度的时间相同,也与 \(v_1\) 相同。于是只计算 \(v_i\)\(v_1\) 的关系,就得到了所有的 \(v_i\)\(v_1\) 的比值。

因为题目要求 \(v_i\) 为整数,所以我们钦定 \(v_1=1\),其余的 \(v_i\) 都以分数的形式维护,最后求分母的最小公倍数 \(x\)

为了字典序最大,将 \(v_i\) 集体乘上 \(\left\lfloor\dfrac hx\right\rfloor x\) 即可。

因为 \(h\leq10^3\),所以可以直接 int 维护。

AC 代码

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
constexpr const int N=1e3,H=1e3;
int n,h,b[N*H+1],id[N*H+1],cnt[H+1];
struct frac{
	int a,b;//a/b
}v[N+1];
bool operator >(frac a,frac b){
	return a.a*b.b>b.a*a.b;
}
bool operator <(frac a,frac b){
	return a.a*b.b<b.a*a.b;
}
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	int T;
	cin>>T;
	while(T--){
		cin>>n>>h;
		for(int i=1;i<=n;i++){
			v[i]={1,1};
		}
		for(int i=1;i<=n*h;i++){
			cin>>b[i];
		}
		for(int i=0;i<h;i++){
			cnt[i]=0;
		}
		for(int i=1;i<=n*h;i++){
			id[i]=++cnt[b[i]];
		}
		int last=h-1;
		for(int i=2;i<=n*h;i++){
			if(id[i]==1){
				last--;
			}else{
				v[id[i]]=min(v[id[i]],{h-b[i],h-last});
			}
		}
		int x=v[1].b;
		for(int i=2;i<=n;i++){
			x=x/__gcd(x,v[i].b)*v[i].b;
		}
		x=h/x*x;
		for(int i=1;i<=n;i++){
			cout<<v[i].a*x/v[i].b<<' ';
		}
		cout<<'\n';
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2026-06-28 13:07  TH911  阅读(2)  评论(0)    收藏  举报