P4309-[TJOI2013]最长上升子序列【Splay】
生活随笔
收集整理的这篇文章主要介绍了
P4309-[TJOI2013]最长上升子序列【Splay】
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
正题
题目链接:https://www.luogu.com.cn/problem/P4309
题目大意
nnn次,第iii次在第xix_ixi个数字后面插入iii然后询问最长上升子序列长度。
解题思路
因为是插入所以考虑用SplaySplaySplay维护,因为从小到大插入,其实每次就是找一个在xix_ixi前面最大的fif_ifi就好了,这个也用SplaySplaySplay维护即可。
时间复杂度O(nlogn)O(n\log n)O(nlogn)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10; int n,cnt,root,f[N],g[N],ans; int t[N][2],fa[N],siz[N]; bool Direct(int x) {return t[fa[x]][1]==x;} void Connect(int x,int y,int dir) {t[x][dir]=y;fa[y]=x;return;} void PushUp(int x){g[x]=max(max(g[t[x][0]],g[t[x][1]]),f[x]);siz[x]=siz[t[x][0]]+siz[t[x][1]]+1;return; } void Rotate(int x){int y=fa[x],z=fa[y];int xs=Direct(x),ys=Direct(y);int w=t[x][xs^1];Connect(z,x,ys);Connect(y,w,xs);Connect(x,y,xs^1);PushUp(y);PushUp(x);return; } void Splay(int x,int f){while(fa[x]!=f){int y=fa[x];if(fa[y]==f)Rotate(x);else if(Direct(x)==Direct(y))Rotate(y),Rotate(x);else Rotate(x),Rotate(x);}if(!f)root=x;return; } int Find(int x,int k){if(siz[t[x][0]]>=k)return Find(t[x][0],k);if(siz[t[x][0]]+1==k)return x;return Find(t[x][1],k-siz[t[x][0]]-1); } int main() {scanf("%d",&n);t[2][0]=siz[1]=siz[2]=1;fa[1]=root=cnt=2;for(int i=1;i<=n;i++){int k;scanf("%d",&k);int x=Find(root,k+1),y=Find(root,k+2);Splay(y,0);Splay(x,y);t[x][1]=++cnt;fa[cnt]=x;f[cnt]=g[cnt]=g[x]+1;siz[cnt]=1;ans=max(ans,f[cnt]);printf("%d\n",ans);PushUp(x);PushUp(y);Splay(cnt,0);}return 0; } 创作挑战赛新人创作奖励来咯,坚持创作打卡瓜分现金大奖总结
以上是生活随笔为你收集整理的P4309-[TJOI2013]最长上升子序列【Splay】的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 怎么倒卖域名(怎么倒卖域名产品)
- 下一篇: P3345-[ZJOI2015]幻想乡战