zoukankan      html  css  js  c++  java
  • BZOJ_3173_[Tjoi2013]最长上升子序列_splay

    BZOJ_3173_[Tjoi2013]最长上升子序列_splay

    Description

    给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

    Input

    第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

    Output

    N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

    Sample Input

    3
    0 0 2

    Sample Output

    1
    1
    2

    HINT

    100%的数据 n<=100000


    分析:由于数字是升序插入的,因此每次操作只会对它一个数产生影响。

    问题转化为:插入一个数,查询某个位置前面的最大值。

    直接用平衡树维护即可。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    #define N 100050
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define get(x) (ch[f[x]][1]==x)
    int f[N],rt,ch[N][2],siz[N],cnt,val[N],mx[N],n,ans;
    void pushup(int p) {
    	if(p) {
    		siz[p]=siz[ls]+siz[rs]+1;
    		mx[p]=max(max(mx[ls],mx[rs]),val[p]);
    	}
    }
    void rotate(int x) {
    	int y=f[x],z=f[y],k=get(x);
    	ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
    	ch[x][!k]=y; f[y]=x; f[x]=z;
    	if(z) ch[z][ch[z][1]==y]=x;
    	pushup(y); pushup(x);
    	if(rt==y) rt=x;
    }
    void splay(int x,int y) {
    	for(int fa;(fa=f[x])!=y;rotate(x))
    		if(f[fa]!=y)
    			rotate(get(fa)==get(x)?fa:x);
    }
    int find(int x) {
    	int p=rt;
    	while(1) {
    		if(x<=siz[ls]) p=ls;
    		else {
    			x-=siz[ls]+1;
    			if(!x) return p;
    			p=rs;
    		}
    	}
    }
    int main() {
    	scanf("%d",&n);
    	int i,x,y,p;
    	for(i=1;i<=n;i++) {
    		scanf("%d",&x);
    		if(x==0) {
    			if(!rt) {
    				rt=i; val[i]=1; siz[i]=1; pushup(i);
    			}
    			else {
    				p=find(1);
    				splay(p,0);
    				val[i]=1; siz[i]=1; f[i]=p; ls=i;
    				pushup(i); pushup(p);
    			}
    		}else if(x==i-1) {
    			p=find(i-1);
    			splay(p,0);
    			val[i]=mx[p]+1; siz[i]=1; f[i]=p; rs=i;
    			pushup(i); pushup(p);
    		}else {
    			int tmp=x;
    			x=find(x); p=find(tmp+1);
    			splay(x,0); splay(p,x);
    			val[i]=max(mx[ch[x][0]],val[x])+1; siz[i]=1; f[i]=p; ls=i;
    			pushup(i); pushup(p); pushup(x);
    		}
    		ans=max(ans,val[i]);
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    ES6 Set
    JavaScript 之 对象属性的特性 和defineProperty方法
    ES6 ... 展开&收集运算符
    ES6 箭头函数
    ES6 解构 destructuring
    canvas之事件交互效果isPointPath
    跨域及JSONP原理
    P03 显示隐藏
    最长公共子序列
    P02 CSS样式
  • 原文地址:https://www.cnblogs.com/suika/p/8891199.html
Copyright © 2011-2022 走看看