hdu 3564 Another LIS splay

题意:依次插入i到pos[i],查询插入后当前LIS。

思路:splay。因为插入的数是升序的,那么对于i,只要知道pos[i]之前的最大LIS---x,那么以i结尾的最大LIS=x+1。那么只要在splay

中,只要维护一个当前区间最大的LIS,插入的时候,把第pos-1位的点旋到根root,把pos位的点旋到根的右结点R(root),新插入的

点插在L(R(root))即可,结点的值max(L(root)->Max,root->val)+1。注意push_up就可以了。详见代码:

/*********************************************************
  file name: hdu3564.cpp
  author : kereo
  create time:  2015年01月29日 星期四 15时49分52秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x->ch[0])
#define R(x) (x->ch[1])
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,cnt,top;
int st[MAXN];
struct node{
    int val,sz,Max;
    node *fa,*ch[2];
}nod[MAXN],nil,*root,*null;
struct Splay{
    void rotate(node *x,int d){
        node *y=x->fa;
        //push_down(y); push_down(x);
        y->ch[d^1]=x->ch[d];
        if(x->ch[d]!=null)
            x->ch[d]->fa=y;
        x->fa=y->fa;
        if(y->fa!=null){
            int d1=y->fa->ch[0] == y ? 0 : 1;
            y->fa->ch[d1]=x;
        }
        x->ch[d]=y; y->fa=x;
        push_up(y);
    }
    void splay(node *x,node *fa){
       while(x->fa!=fa){
            //push_down(x);
            node *y=x->fa;
            if(y->fa == fa){
                int d=y->ch[0] == x ? 1 : 0;
                rotate(x,d);
            }
            else{
                int d=y->fa->ch[0] == y ? 1 : 0;
                if(y->ch[d] == x){
                    rotate(x,d^1); rotate(x,d);
                }
                else{
                    rotate(y,d); rotate(x,d);
                }
            }
       }
       push_up(x);
       if(fa == null) root=x;
    }
    void rotateto(int k,node *fa){
        node *rt=root;
        //push_down(rt);
        while(L(rt)->sz!=k){
            if(L(rt)->sz>k)
                rt=L(rt);
            else{
                k-=(L(rt)->sz+1);
                rt=R(rt);
            }
        }
        //printf("rt=%d fa=%d,L(rt)->sz=%d R(rt)->sz=%d\n",rt-nod,fa-nod,L(rt)->sz,R(rt)->sz);
        splay(rt,fa);
    }
    //----------------------------------------------//
    void init(){
        cnt=top=0;
        nil.sz=nil.val=nil.Max=0;
        nod[0].sz=nod[0].val=nod[0].Max=0;
        null=&nod[0]; root=&nod[0];
        newnode(root,null,0);
        newnode(R(root),root,0);
        push_up(root);
        //printf("root->sz=%d root->val=%d\n",root->sz,root->val);
    }
    void newnode(node *&x,node *fa,int val){
        if(top)
            x=&nod[st[--top]];
        else 
            x=&nod[++cnt];
        x->sz=1; x->val=x->Max=val; 
        x->fa=fa; L(x)=R(x)=null;
    }
    void push_up(node *rt){
        rt->sz=L(rt)->sz+R(rt)->sz+1;
        rt->Max=max(rt->val,max(L(rt)->Max,R(rt)->Max));
    }
    void insert(int pos){
        rotateto(pos-1,null);
        rotateto(pos,root);
        //printf("pos=%d root=%d\n",pos,root-nod);
        newnode(L(R(root)),R(root),max(L(root)->Max,root->val)+1);
        //printf("L(R(root))->val=%d L(R(root))->Max=%d\n",L(R(root))->val,L(R(root))->Max);
        push_up(R(root)); push_up(root);
        printf("%d\n",root->Max);
    }
}spt;
int main(){
    //freopen("in.txt","r",stdin);
    int T,kase=0;
    scanf("%d",&T);
    while(T--){
        spt.init();
        printf("Case #%d:\n",++kase);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            x++;
            spt.insert(x);
        }
        printf("\n");
    }
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值