zoukankan      html  css  js  c++  java
  • Tyvj1208(LIS数量)

    题目链接

    分析:
    之前在xym的hu测中做过这道题,但是代码是急急忙忙码的
    理解不是很深刻,题解说的也不好
    所以只能再来学习一遍

    第一问nlogn,不要写错了

    第二问
    这次是最长上升子序列

    记g[i]为以i结尾,长度是f[i]的子序列的所有方案数

    对于每个f[i]=k来说
    ta都可能是由f[j]=k-1(j

    对于f[j]=k-1所有的j

    如果从小到大排序,那么一定有a[j]>=a[j+1]

    因为如果a[j]

    队中元素的a值单调递减

    前端出队,后端入队
    出队:队首元素的a**大于等于**当前转移点的a(a[i])
    入队:如果f[i]==f[wei]&&a[i]==a[wei],wei–
    a[i] < a[wei]时入队

    开一ans数组,记录f值=i时,队列中的g值之和

    最后计算答案的时候
    f[i]==len
    a[i]单调递减
    利用这个性质,避免重复统计答案

    tip

    还是写代码时别手残

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    
    using namespace std;
    
    int f[1000],l[1000],n,m,a[1000];
    int g[1000],len,ans[1000];
    deque<int>q[1000];
    
    void doit()
    {
        l[1]=a[1];
        f[1]=1;
        int t=1;
        for (int i=2;i<=n;i++)
        {
            if (a[i]>l[t]) l[++t]=a[i],f[i]=t;
            else
            {
                int r=lower_bound(l+1,l+1+t,a[i])-l;
                l[r]=a[i];
                f[i]=r;
            }
        }
        printf("%d
    ",t);
        len=t;
    }
    
    void solve()
    {
        int i,j;
        for (i=1;i<=n;i++)
        {
            if (f[i]==1) g[i]=1;
            else
            {
                int r=f[i]-1;
                while (!q[r].empty()&&a[q[r].front()]>=a[i])
                {
                    ans[r]-=g[q[r].front()];
                    q[r].pop_front();
                } 
                g[i]=ans[r];
            }
            int r=f[i];
            while (!q[r].empty()&&a[q[r].back()]==a[i]) 
            {
                ans[r]-=g[q[r].back()];
                q[r].pop_back();
            }
            ans[r]+=g[i];
            q[r].push_back(i);
        }
        int cnt=0,t=0;
        for (i=n;i>=1;i--)
            if (f[i]==len&&a[i]>t)
               cnt+=g[i],t=a[i];
        printf("%d",cnt);
    }
    
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        doit();
        solve();
        return 0;
    }
  • 相关阅读:
    Python基础闯关失败总结
    fileinput
    squid安装配置
    服务器添加ipa MIME 类型,防止ipa下载后变zip后缀
    单例之懒汉式和饿汉式
    java集合类,详解
    Android 常用动画
    activity和fragment之前运行的生命周期
    Handler 消息传递机制
    startActivityForResult的用法,以及intent传递图片
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673183.html
Copyright © 2011-2022 走看看