【JZOJ6368】質樹(tree)

description

大神 wyp 手裏有棵二叉樹,每個點有一個點權。大神 wyp 的這棵樹是質樹,因爲
隨便找兩個不同的點 u, v,只要 u 是 v 的祖先,都滿足 u 和 v 的點權互質。
現在你通過偷看了解到了大神 wyp 這棵樹的中序遍歷的點權值,你想復原出大神
wyp 的樹,或者指出不可能。
閱讀樣例以更好地理解本題。


analysis

  • 首先預處理質數,對於每個數,可以分解質因數

  • 然後用一個桶前後各掃一遍分別得出每個數往前往後區間內與其都互質的最遠位置

  • 如果對於[l,r][l,r]區間,枚舉一個可行位置ii,拆分成[l,i1],[i+1,r][l,i-1],[i+1,r],複雜度O(n2)O(n^2)

  • 但是如果同時從頭和尾往中間找,每個層搜索長度減半,複雜度O(nlog2n)O(n\log_2n)


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 1000005
#define MAX 10000005
#define ll long long
#define reg register ll
#define ha 1926081719491001
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)

using namespace std;

bool bz[MAX];
ll left[MAXN],right[MAXN];
ll a[MAXN],p[MAX],bucket[MAX],fa[MAXN],mxp[MAX];
ll n,tot,flag=1;

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
inline ll min(ll x,ll y){return x<y?x:y;}
inline void init()
{
	#define MAXX 10000000
	memset(bz,1,sizeof(bz));
	fo(i,2,MAXX)
	{
		if (bz[i])p[++tot]=i,mxp[i]=i;
		for (reg j=1;j<=tot && i*p[j]<=MAXX;++j)
		{bz[i*p[j]]=0,mxp[i*p[j]]=p[j];if (i%p[j]==0)break;}
	}
}
inline bool judge(ll i,ll l,ll r)
{
	if (left[i]<=l && right[i]>=r)return 1;
	return 0;
}
inline void dfs(ll l,ll r,ll x)
{
	if (l>r)return;
	if (l==r){fa[l]=x;return;}
	fo(len,0,(r-l)/2)
	{
		ll i=l+len,j=r-len;
		if (judge(i,l,r))
		{
			fa[i]=x,dfs(l,i-1,i),dfs(i+1,r,i);
			return;
		}
		if (judge(j,l,r))
		{
			fa[j]=x,dfs(l,j-1,j),dfs(j+1,r,j);
			return;
		}
	}
	flag=0;return;
}
int main()
{
	//freopen("T3.in","r",stdin);
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	n=read(),init();fo(i,1,n)a[i]=read();
	fo(i,1,n)
	{
		ll x=a[i];left[i]=1;
		while (x>1)
		{
			ll tmp=mxp[x];
			left[i]=max(left[i],bucket[tmp]?bucket[tmp]+1:1);
			bucket[tmp]=i;
			while (x%tmp==0)x/=tmp;
		}
	}
	memset(bucket,0,sizeof(bucket));
	fd(i,n,1)
	{
		ll x=a[i];right[i]=n;
		while (x>1)
		{
			ll tmp=mxp[x];
			right[i]=min(right[i],bucket[tmp]?bucket[tmp]-1:n);
			bucket[tmp]=i;
			while (x%tmp==0)x/=tmp;
		}
	}
	tot=0,dfs(1,n,0);
	if (!flag){printf("impossible\n");return 0;}
	fo(i,1,n)printf("%lld ",fa[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章