Description
胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤。
——太宰治《人间失格》
回顾我的一生,一共有n个事件,每一个事件有一个幸福值p_i。
我想用n-1条线把所有的事件连起来,变成一个连通块。一条连接了事件x和事件y的线会产生min(p_x mod p_y,p_y mod p_x)的喜悦值。
日日重复同样的事,遵循着与昨日相同的惯例,若能避开猛烈的狂喜,自然也不会有悲痛的来袭。因此,我想知道连接起来之后产生喜悦值最小是多少。
Solution
显然,相同的可以直接合并,
对于每一个
ai
枚举倍数k,对于
aj
,满足
kai≤aj<(k+1)ai
,那么这些数,只有最小的一个是可能与i有边相连的,
那么直接预处理,排序后做Kruscal即可,不过由于边太多了,要用桶排,
复杂度: O(107log(107))
Code
我的程序为正解的阉割版,很难卡掉,但空间极其小(然并卵)
#include <cstdio>
#include <algorithm>
#include <queue>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;
const int N=100500,mo=998244353;
int read(int &n)
{
int w=1;char ch=' ';n=0;
for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-')ch=getchar(),w=-1;
for(;ch<='9'&&ch>='0';ch=getchar())n=n*10+ch-48;
return n=n*w;
}
int n,m,ans;
int a[N];
int d[N][2],d0;
int g[N],bv[N];
bool z[N];
struct qqww
{
int v,i;
friend bool operator <(qqww q,qqww w){return q.v>w.v;}
};
priority_queue<qqww> Ds;
int gf(int q){return g[q]==q?q:(g[q]=gf(g[q]));}
bool PX(int q,int w){return q>w;}
int FD(int q,int t)
{
while(a[q]<t)
{
int i=1;
for(;(i<<1)<=q&&a[q-(i<<1)]<=t;i<<=1);
q-=i;
}
return q;
}
void PRE()
{
fo(i,2,n)
{
// printf("%d\n",i);
int t=a[i];bv[i]=2e9;
for(int j=FD(i-1,t);j>0;t+=a[i],j=FD(j-1,t))
{
if(a[j]-t>=a[i])
{
for(t=(a[j]/a[i])*a[i];a[j]-t>=a[i];t+=a[i]);
}
if(bv[i]>a[j]-t)
{
bv[i]=a[j]-t;
if(!bv[i])break;
}
}
qqww t1;t1.i=i;t1.v=bv[i];
Ds.push(t1);
}
}
int main()
{
freopen("autosadism.in","r",stdin);
freopen("autosadism.out","w",stdout);
int q,w;
read(n);
fo(i,1,n)read(a[i]);
sort(a+1,a+1+n,PX);a[0]=2e9;
if(a[n]<2){printf("0\n");return 0;}
q=0;
fo(i,2,n)
{
a[i-q]=a[i];
if(a[i]==a[i-q-1])q++;
}
n-=q;
ans=0;
fo(i,1,n)g[i]=i;
PRE();
for(int I=1;I<n;)
{
// printf("%d\n",I);
q=(Ds.top()).i;Ds.pop();
int t=a[q],bt=bv[q];bv[q]=2e9;
gf(q);
for(int j=FD(q-1,t);j>0;t+=a[q],j=FD(j-1,t))
{
if(a[j]-t>=a[q])
{
for(t=(a[j]/a[q])*a[q];a[j]-t>=a[q];t+=a[q]);
}
if(g[q]!=gf(j))
{
if(a[j]-t<=bt)
{
I++;
ans+=bt;
g[gf(q)]=g[j];
gf(q);
}else if(bv[q]>a[j]-t)bv[q]=a[j]-t;
}
}
qqww t1;t1.i=q;t1.v=bv[q];
if(bv[q]<1e9)Ds.push(t1);
}
printf("%d\n",ans);
return 0;
}