【NOIP 模拟赛】改造二叉树 最长上升子序列
这道题我一眼就以为是线段树优化dp并且有了清晰的思路但是发现,我不会线段树区间平移,我以为只是我不会,然而根本就不行........
正解是把序列排出来然后我们让他们减去他们的下标之后求最长上升子序列。
#include <cstdio> #include <algorithm> const int N=100500; int n,a[N],b[N],ch[N][2],len,pos[N],c[N],f[N]; void dfs(int x){ if(!x)return; dfs(ch[x][0]); b[++len]=a[x]; dfs(ch[x][1]); } inline int Min(int x,int y){ return x<y?x:y; } inline int Max(int x,int y){ return x>y?x:y; } inline bool comp(int x,int y){ return b[x]<b[y]; } inline int get_Max(int x){ int ret=0; while(x){ ret=Max(ret,c[x]); x-=x&(-x); } return ret; } inline void ins(int x,int y){ while(y<=len){ c[y]=Max(x,c[y]); y+=y&(-y); } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=2,x,y;i<=n;i++){ scanf("%d%d",&x,&y); ch[x][y]=i; } dfs(1); len=0; for(int i=1;i<=n;i++) b[i]-=i,pos[i]=i; std::sort(pos+1,pos+n+1,comp); for(int i=1,last;i<=n;i++){ if(i==1||b[pos[i]]!=last) len++; last=b[pos[i]]; b[pos[i]]=len; } int ans=0; for(int i=1;i<=n;i++){ f[i]=get_Max(b[i])+1; ins(f[i],b[i]); ans=Max(ans,f[i]); } printf("%d",n-ans); }
苟利国家生死以, 岂因祸福避趋之。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步