2017.10.7 最长上升子序列 思考记录

来源:互联网 发布:淘宝神笔怎么用 编辑:程序博客网 时间:2024/06/06 02:25

由于他添加的数字单调上升,所以答案只会在插入的那个数的f值上更新。。

由于之前插入的数都比这个数小,所以直接找区间f最大值。。

这题splay比上个play题好写太多了

不调不试1A  splay辣


码:

#include<iostream>#include<cstdio>using namespace std;int f[100005],g[100005],ch[100005][2],sz[100005],fu[100005],rt,tot,i,ans,k,n;void up(int o){f[o]=max(g[o],max(f[ch[o][0]],f[ch[o][1]]));sz[o]=sz[ch[o][0]]+sz[ch[o][1]]+1;}void set(int a,int wh,int b){ch[a][wh]=b;if(b)fu[b]=a;up(a);}int getwh(int o){return ch[fu[o]][0]==o?0:1;}void rotate(int o){int fa=fu[o],ye=fu[fa];int wh=getwh(o);set(fa,wh,ch[o][wh^1]);set(o,wh^1,fa);fu[o]=ye;if(ye)ch[ye][ch[ye][0]==fa?0:1]=o;}void splay(int o,int tar){for(;fu[o]!=tar;rotate(o))if(fu[fu[o]]!=tar)getwh(o)==getwh(fu[o])?rotate(fu[o]):rotate(o);if(tar==0)rt=o;}int find(int wz){int o=rt;while(1){if(sz[ch[o][0]]+1==wz){splay(o,0);return o;}if(sz[ch[o][0]]+1<wz){wz-=sz[ch[o][0]]+1;o=ch[o][1];}else{o=ch[o][0];}}}int main(){scanf("%d",&n);rt=1;sz[1]=sz[2]=1;set(1,1,2);tot=2;for(i=1;i<=n;i++){scanf("%d",&k);k=ch[find(k+2)][0];++tot;sz[tot]=1;g[tot]=f[k]+1;f[tot]=g[tot];ans=max(ans,g[tot]);while(ch[k][1]!=0)k=ch[k][1];set(k,1,tot);splay(tot,0);printf("%d\n",ans);}}