zoukankan      html  css  js  c++  java
  • 【bzoj3173】[Tjoi2013]最长上升子序列 Treap

    题目描述

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

    输入

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

    输出

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

    样例输入

    3
    0 0 2

    样例输出

    1
    1
    2


    题解

    Treap

    考虑到数据是从小到大插入的,所以每次插入后这个数只会对自身有影响,并不会对前后有影响;而且自身的答案只受其前边位置的答案的影响。

    具体地说,设f[i]表示最后一个数为i的最长上升子序列长度,那么插入时f[i]=max{f[j]}+1(pos(j)<pos(i))。

    查询时查询的是整个f数组的最大值。

    这样就需要一个数据结构,支持插入一个数、查询以1开头的区间的最大值,可以使用Treap搞定。

    这里的insert函数与普通的不同,是指定位置的插入,所以判断时比较的是子树大小。

    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #define N 100010
    using namespace std;
    int f[N] , l[N] , r[N] , si[N] , rnd[N] , maxn[N] , root , tot;
    void pushup(int k)
    {
    	si[k] = si[l[k]] + si[r[k]] + 1 , maxn[k] = max(f[k] , max(maxn[l[k]] , maxn[r[k]]));
    }
    void zig(int &k)
    {
    	int t = l[k];
    	l[k] = r[t] , r[t] = k , si[t] = si[k] , pushup(k) , k = t;
    }
    void zag(int &k)
    {
    	int t = r[k];
    	r[k] = l[t] , l[t] = k , si[t] = si[k] , pushup(k) , k = t;
    }
    void ins(int &k , int x , int w)
    {
    	if(!k) k = ++tot , f[k] = w , rnd[k] = rand();
    	else if(x <= si[l[k]])
    	{
    		ins(l[k] , x , w);
    		if(rnd[l[k]] < rnd[k]) zig(k);
    	}
    	else
    	{
    		ins(r[k] , x - si[l[k]] - 1 , w);
    		if(rnd[r[k]] < rnd[k]) zag(k);
    	}
    	pushup(k);
    }
    int query(int k , int x)
    {
    	if(!k) return 0;
    	if(x <= si[l[k]]) return query(l[k] , x);
    	return max(max(maxn[l[k]] , f[k]) , query(r[k] , x - si[l[k]] - 1));
    }
    int main()
    {
    	int n , x;
    	scanf("%d" , &n);
    	while(n -- ) scanf("%d" , &x) , ins(root , x , query(root , x) + 1) , printf("%d
    " , maxn[root]);
    	return 0;
    }

     

  • 相关阅读:
    一些要学习的文章
    Android 应用检查更新并下载
    Android中如何下载文件并显示下载进度
    android IntentService和ResultReceiver的异步处理
    android 优秀图表库之MPAndroidChart
    android 仿QQ气泡聊天界面
    android canvas中rotate()和translate()两个方法详解
    android 透明弹出搜索框
    【转】ANDROID自定义视图——onLayout源码 流程 思路详解
    【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6856502.html
Copyright © 2011-2022 走看看