题面

CF1437E Make It Increasing

给 \(n\) 个数 \(a_i\),固定 \(k\) 个下标 \(b_i\),求只修改不在 \(b_i\) 中的下标的值使 \(a_i\) 严格单调递增的最少修改次数。

数据范围:\(1\le n\le 5\cdot 10^5\),\(0\le k\le n\)。


题解

分成 \(k+1\) 段做没有问题,蒟蒻的做法是线段树维护 dp

旁边老爷的做法是区间长度减去最长上升子序列长度,蒟蒻没想到,还想了单调队列优化好久。

题目转化为对于一个区间,第一个元素最后一个元素固定的最少修改次数。

把 \(a_i\) 减去 \(i\),就变成非严格单调递增了。

设 \(f_i\) 表示不修改 \(i\) 的前缀最少修改次数。

\[f_i=\min_{j=1,a_j\le a_i}^{i-1} (f_j+i-j-1)\Longrightarrow f_i=i-1+\min_{j=1,a_j\le a_i}^{i-1}( f_j-j)
\]

所以可以建一个 \(a_i\) 值域线段树,值为 \(f_i-i\)。

\(f_i\) 的值就是当前线段树 \([0,a_i]\) 之间的最大值 \(+i-1\)。

每次求出 \(f_i\) 后在 \(a_i\) 上更新 \(f_i-i\) 即可。


代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define bg begin()
#define ed end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),i##E=(b);i<i##E;i++)
#define L(i,a,b) for(int i=(b)-1,i##E=(a)-1;i>i##E;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f; //Data
const int N=5e5+2;
int n,a[N],dn,d[N],k,b[N],ans; //SegmentTree
const int tN=N<<2;
#define mid ((l+r)>>1)
int mn[tN];
void build(int k=0,int l=0,int r=dn){
mn[k]=iinf; if(r-l==1) return;
build(k*2+1,l,mid),build(k*2+2,mid,r);
}
void pushup(int k){mn[k]=min(mn[k*2+1],mn[k*2+2]);}
void fixmn(int x,int v,int k=0,int l=0,int r=dn){
if(r<=x||x+1<=l) return;
if(r-l==1) return mn[k]=min(mn[k],v),void();
fixmn(x,v,k*2+1,l,mid),fixmn(x,v,k*2+2,mid,r),pushup(k);
}
int rangemn(int x,int y,int k=0,int l=0,int r=dn){
if(r<=x||y<=l) return iinf; if(x<=l&&r<=y) return mn[k];
return min(rangemn(x,y,k*2+1,l,mid),rangemn(x,y,k*2+2,mid,r));
} //DP
int tmp[N];
int dp(int* arr,int len){
R(i,dn=0,len) d[dn++]=arr[i];
sort(d,d+dn),dn=unique(d,d+dn)-d;
R(i,0,len) tmp[i]=lower_bound(d,d+dn,arr[i])-d;
build(),fixmn(tmp[0],0); int res=-1;
R(i,1,len){
res=rangemn(0,tmp[i]+1)+i-1;
fixmn(tmp[i],res-i);
}
// R(i,0,len) cout<<arr[i]<<' ';cout<<'\n';
// R(i,0,len) cout<<f[i]<<' ';cout<<'\n';
// cout<<f[len-1]<<'\n';
return res;
} //Main
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>k,a[0]=-iinf,a[n+1]=+iinf;
R(i,1,n+1) cin>>a[i],a[i]-=i;
R(i,0,k) cin>>b[i];
R(i,1,k)if(a[b[i]]<a[b[i-1]]) cout<<-1<<'\n',exit(0);
if(k==0) ans=dp(a,n+2);
else {
ans+=dp(a,b[0]+1);
R(i,1,k) ans+=dp(a+b[i-1],b[i]-b[i-1]+1);
ans+=dp(a+b[k-1],n-b[k-1]+2);
}
cout<<ans<<'\n';
return 0;
}

祝大家学习愉快!

题解-CF1437E Make It Increasing的更多相关文章

  1. 【题解】Greatest Common Increasing Subsequence

    [题解]Greatest Common Increasing Subsequence vj 唉,把自己当做DP入门选手来总结这道题吧,我DP实在太差了 首先是设置状态的技巧,设置状态主要就是要补充不漏 ...

  2. LeetCode题解之Longest Continuous Increasing Subsequence

    1.题目描述 2.问题分析 从每一个num[i]往前扫描即可. 3.代码 int findLengthOfLCIS(vector<int>& nums) { ){ return n ...

  3. Lintcode397 Longest Increasing Continuous Subsequence solution 题解

    [题目描述] Give an integer array,find the longest increasing continuous subsequence in this array. An in ...

  4. LeetCode题解之 Increasing Order Search Tree

    1.题目描述 2/问题分析 利用中序遍历,然后重新构造树. 3.代码 TreeNode* increasingBST(TreeNode* root) { if (root == NULL) retur ...

  5. LeetCode题解之Longest Increasing Subsequence

    1.题目描述 2.题目分析 使用动态规划,在计算以每个字符结尾的最长子序列. 3.代码 int lengthOfLIS(vector<int>& nums) { ){ ; } ve ...

  6. Codeforces Round #160 (Div. 1) 题解【ABCD】

    Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...

  7. LeetCode Longest Increasing Path in a Matrix

    原题链接在这里:https://leetcode.com/problems/longest-increasing-path-in-a-matrix/ Given an integer matrix, ...

  8. 【题解】【数组】【查找】【Leetcode】Search in Rotated Sorted Array

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  9. 300. Longest Increasing Subsequence

    题目: Given an unsorted array of integers, find the length of longest increasing subsequence. For exam ...

随机推荐

  1. ostringstream、istringstream、stringstream(转)

    看一下C++风格的串流控制,C++引入了ostringstream.istringstream.stringstream这三个类,要使用他们创建对象就必须包含sstream.h头文件. istring ...

  2. 02 Filter过滤器

    Filter 一.Filter过滤器 Filter过滤器它是JavaWeb的三大组件之一.三大组件分别是:Servlet程序.Listener监听器.Filter过滤器 Filter过滤器是JavaE ...

  3. [web安全原理]PHP命令执行漏洞基础

    前言 PHP命令执行漏洞 应用程序的某些功能功能需要调用可以执行系统命令的函数,如果这些函数或者函数的参数被用户控制,就有可能通过命令连接符将恶意命令拼接到正常的函数中,从而随意执行系统命令,这就是命 ...

  4. 重闯Sqli-labs关卡第三天(6-10关)

    第六关(双注入GET双引号字符型注) 核心代码: 1 $id = '"'.$id.'"'; 2 $sql="SELECT * FROM users WHERE id=$i ...

  5. 前后端分离中,使用swagger2和WireMock提高开发速度

    一.使用swagger2生成接口文档 依赖 <dependency> <groupId>io.springfox</groupId> <artifactId& ...

  6. 面试官:小伙子,给我说一下Java 数组吧

    Java 数组 Java 语言中提供的数组是用来存储固定大小的同类型元素. 1.声明数组变量 首先必须声明数组变量,才能在程序中使用数组. dataType[] arrayRefVar; // 首选的 ...

  7. Route_of_Linux

    爬过六个陡坡,对Linux了如指掌 本文是极客时间App中刘超老师趣谈Linux操作系统的学习路径课程的学习笔记 抛弃旧思维习惯,熟练使用命令行 要从Windows的思维习惯,切换成Linux的命令行 ...

  8. 攻克solo第七课(Randy Rhoads风格)

    本期文章,笔者将通过Guitar Pro 7吉他软件跟大家分享一下Randy Rhoads的solo句子. 相信很多精研电吉他的朋友都会听过这个一手把Ozzy Osbourne从离开黑色安息日乐队的深 ...

  9. symfony框架中使用service

    在config文件里面的service.yml写入自己service 1 chat.group_list: //service的名字 2 class: Chat\Service\GroupListSe ...

  10. P3287 [SCOI2014]方伯伯的玉米田

    首先可以证明,一定存在一种最优解,每次选择的区间结尾都是 \(n\).因为如果某一个区间结尾不是 \(n\),将其替换成 \(n\) 仍然保持单调不下降.接着都按这个策略拔高玉米. 令 \(f_{i, ...