题面

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. AQS详解,并发编程的半壁江山

    千呼万唤始出来,终于写到AQS这个一章了,其实为了写这一章,前面也是做了很多的铺垫,比如之前的 深度理解volatile关键字 线程之间的协作(等待通知模式) JUC 常用4大并发工具类 CAS 原子 ...

  2. rbd的image对象数与能写入文件数的关系

    前言 收到一个问题如下: 一个300TB 的RBD,只有7800万的objects,如果存储小文件的话,感觉不够用 对于这个问题,我原来的理解是:对象默认设置的大小是4M一个,存储下去的数据,如果小于 ...

  3. Go原生和GoFrame的Cookie关于MaxAge区别

    Go原生和GoFrame的Cookie关于MaxAge区别 环境: gf v1.14.4 go 1.11 Go原生 type Cookie struct { Name string Value str ...

  4. Git本地仓库和远程仓库冲突解决

    场景描述: 在本地创建了一个git repo,并且执行了,git init命令,创建了.gitignore文件,或者README.md文件: 在远程创建了一个git repo,创建时也初始化了.git ...

  5. CorelDRAW不同选择工具的作用及用法汇总

    在CorelDRAW中,"选择工具"是我们的好助手之一."选择工具"图标位于CDR界面左边的工具箱中.使用鼠标单击图标右下角的小三角,我们可以看到"选 ...

  6. 关于Boom 3D“夜间模式”的妙用

    Boom 3D的"夜间模式"不仅能够优化音效,减小高分贝声音的突然刺激,让你夜晚的聆听效果更加舒适,还能将音效运用到各种环境中. 下面小编就给大家讲一讲如何更好的利用Boom 3D ...

  7. guitar pro系列教程(十四):Guitar Pro教程之创建新乐谱后的设置

    前面的章节我们有对Guitar Pro的单个功能作介绍,对于初学作曲,且又是吉他初学者的朋友们来说,学完这些功能介绍,自己还不能融会贯通起来,创建了一个新的乐谱后,但是看起来还不是很满意,今天我们就创 ...

  8. FL studio系列教程(四):如何利用FL Studio进行音乐合并

    FL Studio20是Fruity Loops Studio的简称,也叫做水果音乐制作软件.它是一款功能十分强大的音乐制作软件,将作曲.编曲.混音.录音.大碟等功能集合一体,外接MIDI即可成为一个 ...

  9. leetcode152. 乘积最大子序列

    给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数).示例 1:输入: [2,3,-2,4]输出: 6解释: 子数组 [2,3] 有最大乘积 6.示例 2:输入: ...

  10. recovery.sh

    #!/bin/bash source /etc/profile Time=`date +%F-%H-%M` Dir=/data/any.service.recovery if [ ! -d $Dir ...