zoukankan      html  css  js  c++  java
  • CF1437E Make It Increasing 题解

    题目大意

    给你一个数列 (a) ,一个集合 (b) , 对于每个(b) 中的元素(x)(a_x) 不能修改,其他都可以修改,问最少多少次可以将(a) 修改为严格单调递增的。如果不存在,输出 (-1)

    思路

    我们先考虑不存在的情况,一定是存在(x,yin b,x < y) ,(a_y-a_x < y-x) , 这样无法在 (a_x,a_y) 中任意修改满足严格单调递增。


    那么接下来考虑最小的修改次数。

    加入我们没有修改限制呢?

    那么就是一个经典的(DP) 问题了。

    我们将原数组变形,让(a_x = a_x -x),然后跑一遍最长不下降子序列就行了(用 (nlogn) 的算法),答案就是 (n-)最长不下降子序列长度了。

    但是有限制,我们先考虑一下没有限制的代码。

    for(int i = 1;i <= n;i++) a[i] -= i;
    for(int i = 1;i <= n;i++){
    	if(e == 0 || a[i] >= l[e]) {
    	    l[++e] = a[i];
    	}
    	else{
    	    int p = upper_bound(l+1,l+e+1,a[i])-l;
    	    l[p] = a[i];
    	}
    }//e : l 数组的末尾标号。
    

    这样的代码会在遍历 (a) 数组时不断更新自己的一个假想的答案序列,使它每个值尽可能的小,然后容下一个新的值,使答案最大。

    在判过是否满足后,(forall xin b)(a_x) 一定也可以在处理后形成一个不下降子序列,我们要保证不修改它们,就要让它们处于这个假想的答案序列中,于是我们可以加上几行:

    //lasb ,上一个不能修改的位置在我们当前维护的假想答案序列中的位置。
    //ban[i] , a[i] 是否禁止修改。
    for(int i = 1;i <= n;i++){
    	if(e == 0 || a[i] >= l[e]) {
    	    l[++e] = a[i];
    	    if(ban[i]) lasb = e;
    	}
    	else{
    	    int p = upper_bound(l+1,l+e+1,a[i])-l;
    	    if(p <= lasb) continue;//如果我们要更改的位置小于上一个不能修改的位置,那么就不能更改假想的答案序列
    	    l[p] = a[i];
    	    if(ban[i]) lasb = p,e = p;//答案序列p后面的位置都不满足条件,因为它们不能大于这个不能修改的位置,因此对我们要的最长不下降子序列不能产生贡献。
    	}
    }
    

    魔改一下这个算法后,就可以(AC) 了。(具体理解见代码,可以结合一下(nlogn)的最长不下降子序列的算法)

    Code

    #define re(x) read(x)
    
    const int MAXN = 1e6+10;
    
    int n,k;
    int a[MAXN],l[MAXN],e,b[MAXN],lasb=0;
    bool ban[MAXN];
    
    int main (){
        re(n);re(k);
        for(int i = 1;i <= n;i++) re(a[i]);
        for(int i = 1;i <= k;i++) re(b[i]),ban[b[i]]=1;
        sort(b+1,b+k+1);
        for(int i = 2;i <= k;i++)
    		if(a[b[i-1]] - b[i-1] > a[b[i]] - b[i]){
    	    	return puts("-1"),0;
    		}
        for(int i = 1;i <= n;i++) a[i] -= i;
        for(int i = 1;i <= n;i++){
    		if(e == 0 || a[i] >= l[e]) {
    	    	l[++e] = a[i];
    	    	if(ban[i]) lasb = e;
    		}
    		else{
    	    	int p = upper_bound(l+1,l+e+1,a[i])-l;
    	    	if(p <= lasb) continue;
    	    	l[p] = a[i];
    	    	if(ban[i]) lasb = p,e = p;
    		}
        }
        printf("%d",n-e);
        return 0;
    }
    
  • 相关阅读:
    linux下安装qt-4.5_for_TQ210_V1.0.(TQ210)-ubuntu11.10过程出现的问题
    15+ 易响应的CSS框架快速开启你的敏捷网站项目
    分享10个超实用的jQuery代码片段
    免费数据库+免费空间建站
    25个令人难忘的广告设计
    android实现点击效果
    ServletContextListener
    ServletContext
    一个不错的地址--类序列化等
    Java的运行时数据存储机制
  • 原文地址:https://www.cnblogs.com/werner-yin/p/-solution-CF-1437E.html
Copyright © 2011-2022 走看看