zoukankan      html  css  js  c++  java
  • 「Luogu P5080 Tweetuzki 爱序列」

    题目大意

    给出一些数,需要求出 (frac{a_{i+1}}{3}=a_i)(a_{i+1}=2 imes 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
    ",answer);//输出答案
    	int now=st;
    	while(now)
    	{
    		printf("%lld ",a[now]);
    		now=nxt[now];
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    UITextView自适应高度解决方法
    UITextView自适应高度出现的问题
    UITextView出现的一些问题
    服务器终于好了!
    Update语句
    VS.NET经验与技巧
    唯一约束
    由C#风潮想起的-给初学编程者的忠告
    location.search在客户端获取Url参数的方法
    Web Services 入门概念
  • 原文地址:https://www.cnblogs.com/Sxy_Limit/p/12372098.html
Copyright © 2011-2022 走看看