題解 CF1437E 【Make It Increasing】
阿新 • • 發佈:2020-12-02
Solution CF1437E Make It Increasing
題目大意:給定一個序列,以及一些不能被修改的位置。問最少修改幾個數可以使得序列嚴格單調遞增。
dp
分析:
首先經典結論,把每個數減去它的下標,這樣我們就只需要使得序列單調不降就可以了,元素可以相同更方便一些。
最少修改幾個數,可以轉化為,我們要在序列中選取一個最長不下降子序列,修改其他位置的值。而那些不能被修改的位置,就是我們必須選入子序列的位置。
這樣我們沿用 \(nlogn\) 的經典做法,只不過稍加改動。設上一個欽定被選擇的位置為 \(pre\),下一個位置為 \(nxt\),那麼當前的位置 \(p\)
#include <cstdio> #include <cctype> #include <cstring> #include <algorithm> #include <vector> #pragma GCC optmize(2) using namespace std; typedef long long ll; constexpr int maxn = 5e5 + 100,inf = 0x7fffffff; struct IO{//-std=c++11,with cstdio and cctype private: static constexpr int ibufsiz = 1 << 20; char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf; static constexpr int obufsiz = 1 << 20; char obuf[obufsiz + 1],*onow = obuf; const char *oed = obuf + obufsiz; public: inline char getchar(){ #ifndef ONLINE_JUDGE return ::getchar(); #else if(inow == ied){ ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin); *ied = '\0'; inow = ibuf; } return *inow++; #endif } template<typename T> inline void read(T &x){ static bool flg;flg = 0; x = 0;char c = getchar(); while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar(); while(isdigit(c))x = x * 10 + c - '0',c = getchar(); if(flg)x = -x; } template <typename T,typename ...Y> inline void read(T &x,Y&... X){read(x);read(X...);} inline int readi(){static int res;read(res);return res;} inline long long readll(){static long long res;read(res);return res;} inline void flush(){ fwrite(obuf,sizeof(char),onow - obuf,stdout); fflush(stdout); onow = obuf; } inline void putchar(char c){ #ifndef ONLINE_JUDGE ::putchar(c); #else *onow++ = c; if(onow == oed){ fwrite(obuf,sizeof(char),obufsiz,stdout); onow = obuf; } #endif } template <typename T> inline void write(T x,char split = '\0'){ static unsigned char buf[64]; if(x < 0)putchar('-'),x = -x; int p = 0; do{ buf[++p] = x % 10; x /= 10; }while(x); for(int i = p;i >= 1;i--)putchar(buf[i] + '0'); if(split != '\0')putchar(split); } inline void lf(){putchar('\n');} ~IO(){ fwrite(obuf,sizeof(char),onow - obuf,stdout); } }io; template <typename A,typename B> inline void chkmin(A &x,const B &y){if(y < x)x = y;} template <typename A,typename B> inline void chkmax(A &x,const B &y){if(y > x)x = y;} int val[maxn],g[maxn],ans; vector<int> pos; int main(){ const int n = io.readi(),k = io.readi(); for(int i = 1;i <= n;i++)io.read(val[i]),val[i] -= i; pos.push_back(0); for(int i = 1;i <= k;i++)pos.push_back(io.readi()); for(unsigned int i = 2;i < pos.size();i++) if(val[pos[i - 1]] > val[pos[i]])return io.write(-1,'\n'),0; pos.push_back(n + 1); val[0] = -inf; val[n + 1] = inf; memset(g,0x7f,sizeof(g)); for(int i = 1;i <= n;i++){ int nxt = *upper_bound(pos.begin(),pos.end(),i); int pre = *prev(lower_bound(pos.begin(),pos.end(),i)); if(val[i] > val[nxt] || val[i] < val[pre])continue; int p = upper_bound(g + 1,g + n,val[i]) - g; if(nxt == n + 1)chkmax(ans,p); g[p] = val[i]; } return io.write(n - ans,'\n'),0; }