zoukankan      html  css  js  c++  java
  • 【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;//把两个答案加起来输出
    }
    
  • 相关阅读:
    软件工程结对第二次作业
    软件工程结对第一次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    实验九:根据材料编程
    实验五:编写、调试具有多个段的程序
    实验4:[bx]和loop的使用
    《汇编语言》实验三——编程、编译、连接、跟踪
    《汇编语言》实验二——用机器指令和汇编指令编程
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4282.html
Copyright © 2011-2022 走看看