参考:https://vjudge.net/solution/2633272
题意:
给定一个序列,删除最少的数使得任意两个相邻的数的abs不会相差1,
看来自己还是不太熟悉线段树,原本居然不知道怎么处理这个地方的用线段树的优化..
#include<bits/stdc++.h>
using namespace std;
#define up 1000000
#define N 100050
#define LL long long
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define inf 0x3f3f3f3f
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ls,ll, md
#define rson rs,md + 1, rr
int n,dp[N],mx[up<<2],id[up<<2],c[N];
int ans[up<<2],last[up<<2];
void query(int i,int ll,int rr,int a,int b,int j){
if(a>b)return;
if(ll==a&&rr==b){
if(mx[i]>dp[j])dp[j]=mx[i],last[j]=id[i];
}
else{
if(b<=md)query(lson,a,b,j);
else if(a>md)query(rson,a,b,j);
else{
query(lson,a,md,j);
query(rson,md+1,b,j);
}
}
}
void update(int i,int ll,int rr,int a,int b,int c){
if(ll==rr)mx[i]=b,id[i]=c;
else{
if(a<=md)update(lson,a,b,c);
else update(rson,a,b,c);
if(mx[ls]>mx[rs])
mx[i]=mx[ls],id[i]=id[ls];
else mx[i]=mx[rs],id[i]=id[rs];
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&c[i]);
for(int i=1;i<=n;++i){
last[i]=0,dp[i]=0;
query(1,0,up,0,c[i]-2,i);
query(1,0,up,c[i],c[i],i);
query(1,0,up,c[i]+2,up,i);
dp[i]++;
update(1,0,up,c[i],dp[i],i);
}
query(1,0,up,0,up,n+1);
printf("%d\n",n-dp[n+1]);
int p=0;
for(int i=last[n+1];i!=0;i=last[i])ans[p++]=i;
for(p--;p>=0;--p){
printf("%d ",c[ans[p]]);
}puts("");
}