• 【BZOJ4282】慎二的随机数列(水题)


    点此看题面

    大致题意: 给你一个序列,其中有一些元素可以任意填,求最大化严格最长上升子序列长度。

    贪心

    显然,选择全部任意填的元素一定能得到最优答案。(因为你就算选了一个已知的数,也可以拿任意填的数去替代它)

    那我们就把它们先取完,然后考虑剩下这个序列。

    我们发现,假如(i)(j)之间有(x)个任意填的元素,则(a_j)需要大于(a_i+x)才能同时选择它们两个。

    也就是说,设(s_i)为前(i)个数中任意填的元素个数,那么能同时选(a_i,a_j),就需要满足(a_j-s_j>a_i-s_i)

    所以我们直接对({a_i-s_i})这个序列做一次最长上升子序列,再把答案加上任意填的元素个数就可以了。

    众所周知最长上升子序列是可以通过二分实现(O(nlogn))的,于是这题就做完了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    using namespace std;
    int n,cnt,a[N+5];
    I void Ins(CI x)//往最长上升子序列中加一个元素
    {
    	if(!cnt||x>a[cnt]) return (void)(a[++cnt]=x);//如果大于已有的所有数
    	RI l=1,r=cnt,mid;W(l<r) a[mid=l+r-1>>1]>=x?r=mid:l=mid+1;a[r]=x;//二分找到它的位置
    }
    int main()
    {
    	RI i,t=0,x;char op;for(scanf("%d",&n),i=1;i<=n;++i)
    		cin>>op,op^'N'?(scanf("%d",&x),Ins(x-t),0):++t;//t统计当前任意填的元素个数
    	return printf("%d",cnt+t),0;//把两个答案加起来输出
    }
    
  • 相关阅读:
    2行2列分别使用逗号串连起来
    动态获取数据表或临时表列名
    判断临时表是否存在
    RICOH C4502彩色打印机取消双面打印功能
    UNPIVOT逆透视以及动态逆透视存储过程
    动态透视表
    MS SQL的CASE...WHEN...THEN...END语法
    获取数据库中所有触发器
    动态表名,列名,输入参数,输出参数等
    使用CTE生成辅助表(数字或时间)等
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4282.html
Copyright © 2020-2023  润新知