486E - LIS of Sequence(LIS)

本文详细介绍了如何通过NLGN算法计算序列的最长递增子序列,并进一步分析每个元素在所有可能的LIS中的角色。通过算法优化和后处理步骤,明确区分元素是否存在于至少一条LIS中、存在于所有LIS中还是不存在于任何LIS中。

题意:给一个长度为n的序列,问每个数关于序列的LIS(longest increasing subsequence)是什么角色。这里分了三种:

          1、此数没有出现在任意一条LIS中

          2、此数出现在至少一条但是不是全部的LIS中

          3、此数出现在所有的LIS中

解法:nlgn的LIS算法可以求出以每个i位置结束的LIS长度up[i]。出现在LIS的数其实就是一个dag,找出那些某层唯一数值的数就行。LIS算法后,从后向前扫,维护所以长度的最大值,这中间可以判断某长度有几个值,如果某些长度有多个位置则他们都属于2,如果某长度只有一个位置则属于3,其余都是非LIS元素。在判断多个的时候,某个数num[i]可以松弛他的长度位置,条件要保证他比此时help[up[i+1]]的数小,因为这样才能保证他在LIS中(LIS最后一个元素是特判的)。


代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#define inf 10000000

using namespace std;
const int Max=100010;
int num[Max];
int up[Max];
int down[Max];
int D[Max];
void getLIS(int num[],int n)
{
    int last=0;
    for(int i=0; i<n; i++)
    {
        up[i]=lower_bound(D,D+last,num[i])-D+1;
        if(up[i]>last) D[last = up[i]]=num[i];
        D[up[i]-1]=num[i];
    }
}
int help[Max];
int ne[Max];
int ans[Max];
int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            scanf("%d",num+i);
        getLIS(num,n);
        int ma=0;
        for(int i=n-1; i>=0; i--)
            ma=max(ma,up[i]);
        for(int i=n-1; i>=0; i--)
        {
            if(up[i]==ma)
            {
                if(help[up[i]]==0)
                    ans[i]=3,ne[ma]=i;
                else
                {
                    ans[i]=2;
                    ans[ne[ma]]=2;
                    ne[ma]=i;
                }
                help[up[i]]=num[i];
            }
            else
            {
                if(num[i]>=help[up[i]+1])
                    ans[i]=1;
                else
                {
                    if(help[up[i]]==0)
                        ans[i]=3,ne[up[i]]=i;
                    else
                    {
                        ans[i]=2;
                        ans[ne[up[i]]]=2;
                        ne[up[i]]=i;
                    }
                    help[up[i]]=num[i];
                }
            }
        }
        for(int i=0; i<n; i++)
            cout<<ans[i];
        cout<<endl;
    }
    return 0;
}

【源码免费下载链接】:https://renmaiwang.cn/s/i6otc 在本文中,我们将深入探讨如何使用Verilog语言实现CNN(卷积神经网络)并在FPGA上进行部署。这个项目特别关注卷积层、池化层和全连接层的硬件实现,利用Xilinx的Vivado 2019.2集成设计环境。同时,它还包含了测试平台(testbench),以便于验证和调试设计的功能正确性。**1. Verilog简介**Verilog是一种硬件描述语言,常用于数字电子系统的建模和设计。它允许工程师以一种结构化的方式描述电路行为,可以用于仿真、综合和验证数字系统,包括在FPGA上的实现。**2. CNN基础知识**卷积神经网络(CNN)是深度学习中的关键组成部分,尤其在图像识别和处理领域表现出色。CNN由多个层次组成,包括卷积层、池化层和全连接层。- **卷积层**:是CNN的核心,通过卷积核(滤波器)对输入图像进行滑动运算,提取特征。每个卷积核会生成一个特征映射,这些映射共同构成特征图。- **池化层**:用于减小数据维度,降低计算复杂性,同时保持关键信息。常见的池化操作有最大池化和平均池化。- **全连接层**:在CNN的最后阶段,将所有特征图展平为一维向量,并连接到一个或多个全连接层,用于分类或回归任务。**3. Vivado 2019.2简介**Xilinx的Vivado是一款综合性的设计工具,支持FPGA的开发流程,包括IP核开发、逻辑综合、时序分析、布局布线等。Vivado 2019.2版本提供了更高效的设计环境和优化工具,使得硬件实现CNN成为可能。**4. CNN硬件实现**在FPGA上实现CNN,通常会针对特定层进行优化。例如:- **卷积层**:可以采用并行处理策略,每个处理单元负责一部分卷积计算,提高计算速度。- **池化层**:通常较为简单,可以直接硬件实现。- **全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值