zoukankan      html  css  js  c++  java
  • cf 1437E. Make It Increasing

    题目链接:传送门

    题目大意:

    对序列a的任意一个数字进行赋值操作(除了下标属于setb的数字),使得序列 a 变成严格单增的序列,ai+1 > ai;

    题目思路:

    显然,对于一个严格单增的序列: ai+1 >= ai+1  ,  aj - ai >= j - i ;

    对于 i ∈ setb ,ai 是不可修改的, 那么 i、j ∈ set_b  , 若 aj - ai < j - i 则 无解;

    接下来考虑一定有解的情况,

    如果setb 为空 ,那么显然就可以直接求最长单调上升子序列,然后修改不属于最长子序列的数字;

    如果setb 不为空, 修改后的序列 a 须满足 aj - ai >= j - i  -->  aj - j >= ai - i ,

    那么构造序列 bi = ai - i,

    分段求出每一段的最长单调不下降子序列即可。

    那么,为什么需要构造序列b,而不能直接对序列a分段求最长上升子序列呢?

    答案是显然的,假设 ai aj 是最长上升子序列的两个相邻元素,那么有 aj > ai ,但是 不一定满足 aj - ai >= j - i, 那么这个最长上升子序列不就不能满足之前的必要条件。因此,直接求LIS ,是无法保证筛选出来的子序列是一定满足aj - ai >= j - i的, 所以才要构造序列b 来保证aj - j >= ai - i。

    代码:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(2)
     3 using namespace std;
     4 typedef long long LL;
     5 typedef unsigned long long uLL;
     6 typedef pair<int,int> pii;
     7 typedef pair<LL,LL> pLL;
     8 typedef pair<double,double> pdd;
     9 const int N=5e5+5;
    10 const int M=8e5+5;
    11 const int inf=0x3f3f3f3f;
    12 const LL mod=1e8+7;
    13 const double eps=1e-8;
    14 const long double pi=acos(-1.0L);
    15 #define ls (i<<1)
    16 #define rs (i<<1|1)
    17 #define fi first
    18 #define se second
    19 #define pb push_back
    20 #define eb emplace_back
    21 #define mk make_pair
    22 #define mem(a,b) memset(a,b,sizeof(a))
    23 LL read()
    24 {
    25     LL x=0,t=1;
    26     char ch;
    27     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
    28     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    29     return x*t;
    30  
    31 }
    32 int a[N],s[N],b[N];
    33 int main()
    34 {
    35     int n=read(),k=read();
    36     for(int i=1;i<=n;i++) a[i]=read()-i;
    37     for(int i=1;i<=k;i++) b[i]=read();
    38     a[b[0]=0]=-inf,a[b[k+1]=n+1]=inf;
    39     int flag=0;
    40     for(int i=2;i<=k;i++)
    41         if(a[b[i]]<a[b[i-1]]) flag=1;
    42     if(flag) return 0*printf("-1
    ");
    43     int top=0,ans=0;
    44     for(int i=0;i<=k;i++)
    45     {
    46         for(int j=b[i];j<b[i+1];j++)
    47         {
    48             if(top==0||s[top]<=a[j]) s[++top]=a[j];
    49             else
    50             {
    51                 int pos=upper_bound(s+1,s+top+1,a[j])-s;
    52                 if(pos>1) s[pos]=a[j];
    53             }
    54         }
    55         ans+=(upper_bound(s+1,s+top+1,a[b[i+1]])-s)-1;
    56         top=0;
    57     }
    58     printf("%d
    ",n-ans+1);
    59     return 0;
    60 }
    View Code
  • 相关阅读:
    getContentResolver()内容解析者查询联系人、插入联系人
    ContentProvider备份短信,以xml文件存储
    ContentProvider详解
    bindService初步了解
    Service之来电监听(失败的案例)
    Android帧动画
    AlertDialog之常见对话框(单选对话框、多选对话框、进度条对话框)
    BroadcastReceiver之(手动代码注册广播)屏幕锁屏、解锁监听、开机自启
    BroadcastReceiver之有序广播
    [FJOI2015]火星商店问题
  • 原文地址:https://www.cnblogs.com/DeepJay/p/13934300.html
Copyright © 2011-2022 走看看