「Luogu P5080 Tweetuzki 爱序列」

题目大意

给出一些数,需要求出 \(\frac{a_{i+1}}{3}=a_i\)\(a_{i+1}=2 \times a_i\) 时最长的序列 \(a\).

分析

可以发现符合条件的序列 \(a\) 中不会出现重复的数字,而且对于一个数它的下一个位置最多只有两种情况,于是问题就变成了无环有向图最长链,这样就可以想到记忆化搜索,\(f_i\) 表示 \(i\) 为起点时的最长链长度,为了记录下路径,所以还需要用一个 \(nxt_i\) 表示 \(i\) 的下一个位置时什么,最后直接输出就好了.

代码

#include<bits/stdc++.h>
#define REP(i,first,last) for(int i=first;i<=last;++i)
#define DOW(i,first,last) for(int i=first;i>=last;--i)
using namespace std;
const int MAXN=1e6+7;
int N;
struct Edge//链式前向星
{
	int to,next;
}edge[MAXN*2];
int edge_head[MAXN];
int edge_cnt=0;
#define TO_POINT(now) for(int edge_i=edge_head[now];edge_i;edge_i=edge[edge_i].next)
#define TO edge[edge_i].to
void AddEdge(int f,int t)
{
	edge[++edge_cnt].to=t;
	edge[edge_cnt].next=edge_head[f];
	edge_head[f]=edge_cnt;
}
bool visit[MAXN];
long long arr[MAXN];//原数组
long long a[MAXN];//去重以后的数组
int f[MAXN];//记录每个位置的最长链长度
int Find(long long num)//二分查找是否存在这个数
{
	int left=1,right=N,middle;
	while(left<=right)
	{
		middle=(left+right)>>1;
		if(a[middle]>=num)
		{
			right=middle-1;
			if(a[middle]==num)
			{
				return middle;
			}
		}
		else
		{
			left=middle+1;
		}
	}
	return 0;
}
int nxt[MAXN];//记录下一个位置
void DFS(int now)//DFS
{
	if(f[now])//如果搜索过就不需要搜索了
	{
		return;
	}
	f[now]=1;//开始的长度为1
	TO_POINT(now)
	{
		DFS(TO);
		if(f[TO]+1>f[now])//找到在自己连出的边中的最长链长度
		{
			f[now]=f[TO]+1;
			nxt[now]=TO;//记录下一个位置
		}
	}
}
int main()
{
	scanf("%d",&N);
	REP(i,1,N)
	{
		scanf("%lld",&arr[i]);
	}
	sort(arr+1,arr+1+N);
	arr[0]=arr[1]-1;
	int cnt=0;
	REP(i,1,N)//去重
	{
		if(arr[i]!=arr[i-1])
		{
			a[++cnt]=arr[i];
		}
	}
	N=cnt;
	int l;
	REP(i,1,N)//对于每一个点连边
	{
		if(a[i]%3==0)//需要判断整除
		{
			l=Find(a[i]/3);
			if(l)
			{
				AddEdge(i,l);
			}
		}
		l=Find(a[i]*2);
		if(l)
		{
			AddEdge(i,l);
		}
	}
	int answer=0,st;
	REP(i,1,N)//如果没有访问过就DFS这个位置
	{
		if(!f[i])
		{
			DFS(i);
		}
		if(f[i]>answer)//记录下最长链的开头
		{
			answer=f[i];
			st=i;
		}
	}
	printf("%d\n",answer);//输出答案
	int now=st;
	while(now)
	{
		printf("%lld ",a[now]);
		now=nxt[now];
	}
	return 0;
}

posted @ 2020-02-27 14:43  SxyLimit  阅读(116)  评论(0编辑  收藏  举报