题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5427
因为noip,博客咕了好久,这几天集中填一下坑。
这题我们可以假设往不确定的空位里填数,然后考虑一下如何尽可能让空位多被选上。我们发现,如果有一个空位没在最后的最长上升子序列里,那么可以贪心地去掉一个被选上的数再加上去。
那么我们假定所有的空位都被选上。这样原序列就被划分成了许多段,而每一段内的在最长上升子序列里的数都必须与两边相差至少2(留一个数给空位)。那么我们可以把每一段数整体减去前面空位的数量(即每个数的数值减去前面没被确定的数的个数),然后直接跑一遍最长上升子序列,加上空位数量就行了。
代码:
#include<cstdio> #include<set> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int read(){int tmp=0; char c=nc(),f=1; for(;c<'0'||'9'<c;c=nc())if(c=='-')f=-1; for(;'0'<=c&&c<='9';c=nc())tmp=(tmp<<3)+(tmp<<1)+c-'0'; return tmp*f;} set<int>st; int n,k,delta=0; int main() { n=read(); for(int i=1;i<=n;i++){ char ch=nc(); while(ch<'A'||'Z'<ch)ch=nc(); if(ch=='K'){ k=read(); set<int>::iterator iter=st.lower_bound(k-delta); if(iter==st.end())st.insert(k-delta); else if(*iter+delta>k)st.erase(iter),st.insert(k-delta); } else{ ++delta; st.insert(-1000000000-delta); } } printf("%d ",st.size()); }