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);
    	}
    }
    
  • 相关阅读:
    JavaWeb学习(17):优化三层(加入接口和 DBUtil)
    [每日一题]:The Lazy Cow(silver)
    JavaWeb学习(16): 三层架构模式实现简单的学生管理系统(内含数据库)
    BZOJ3275Number——二分图最大权独立集
    BZOJ3438小M的作物——最小割
    BZOJ2127happiness——最小割
    BZOJ3894文理分科——最小割
    BZOJ2150部落战争——最小路径覆盖
    BZOJ4205卡牌配对——最大流+建图优化
    BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
  • 原文地址:https://www.cnblogs.com/suika/p/8891199.html
Copyright © 2011-2022 走看看