TJOI2013 最长上升子序列
维护动态序列 支持插入和查询区间最大值
平衡树上要维护两个权值:
一个是这个点所代表的dp值
一个是val值 代表dp最大值 两个不能重叠 否则在分裂的时候会出错
#include <iostream>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdlib>
using namespace std;
const int N=2e5+10;
int read()
{
int x=0,f=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return f?-x:x;
}
int sz[N],lch[N],rch[N],rnd[N],dp[N],val[N],pos[N];
int root,rx,ry,rz,cnt;
int n,m;
//注意这题有个特殊的条件: 加入的数一直是递增的
//所以当前序列中已经有的值一定比较小
void upd(int x)
{
sz[x]=sz[lch[x]]+sz[rch[x]]+1;
val[x]=max( max(val[lch[x]],val[rch[x]]), dp[ pos[x]] );
}
void split(int now,int k,int &x,int &y)
{
if(!now){ x=y=0; return;}
if(k>=sz[lch[now]]+1){ x=now; split(rch[now],k-sz[lch[now]]-1,rch[x],y);}
else { y=now; split(lch[now],k,x,lch[y]);}
upd(now);
}
int merge(int x,int y)
{
if(!x||!y) { return x+y;}
if(rnd[x]<rnd[y]){ rch[x]=merge(rch[x],y); upd(x); return x;}
else { lch[y]=merge(x,lch[y]); upd(y); return y;}
}
int _new(int x,int i){ rnd[++cnt]=rand(); sz[cnt]=1; dp[i]=x;val[cnt]=x; pos[cnt]=i;return cnt;}
int main()
{
srand(1);
n=read();
for(int i=1;i<=n;i++)
{
int p=read()+1;
split(root,p-1,rx,ry);
root=merge( merge(rx,_new( val[rx]+1,i ) ) ,ry) ;
printf("%d\n",val[root]);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】