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;
}
时间: 2024-10-14 19:00:53

hdu 3564 Another LIS splay的相关文章

HDU 3564 Another LIS splay(水

题意: 给定一个空序列 插入n个数(依次插入 1.2.3.4··n) 以下n个数表示i插在哪个位置. 每插入一个数后输出这个序列的lis 然后... 由于每次插入的数都是当前序列最大的数 所以不会影响后面的数的dp值 那么这个位置的dp值就是插入位置的前面最大dp值+1 然后输出这个序列最大的dp值. == 思路: splay. .. Q:为何这题须要用splay,不是简单的线段树吗 A: 由于我智商不够想不出线段树怎么写.. #include <cstdio> #include <io

Hdu 3564 Another LIS 线段树+LIS

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1361    Accepted Submission(s): 492 Problem Description There is a sequence firstly empty. We begin to add number from 1 to N to the sequence, and

hdu 4441 Queue Sequence(splay)

题目链接:hdu 4441 Queue Sequence 这题看了题解写的,题解传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt<<1|1 5 using namespace std; 6 typedef long long ll; 7 8 const int N=1e6+7; 9 i

hdu 1890 Robotic Sort(splay 区间反转+删点)

题目链接:hdu 1890 Robotic Sort 题意: 给你n个数,每次找到第i小的数的位置,然后输出这个位置,然后将这个位置前面的数翻转一下,然后删除这个数,这样执行n次. 题解: 典型的splay区间翻转+删点. 我们把数据排序,然后记录一下每个数原来的位置,然后splay建树的时候用原来的位置来对应,这样val[i].second就直接是这个数在splay中的那个节点. (当然你也可以普通建树,然后手动记录位置). 然后我们把要找的那个数对应的节点旋转到根,然后根左边的size+i就

hdu 1423(LCS+LIS)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1423 好坑啊..还有公共串为0时的特殊判断,还有格式错误..看Discuss看知道除了最后一组测试数据之外都需要空行.. 其余的会LCS打印路径就行了. ///公共最长上升子序列 #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <

HDU 1890 - Robotic Sort - [splay][区间反转+删除根节点]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1890 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Somewhere deep in the Czech Technical University buildings, there are laboratories for examining

HDU 1890 Robotic Sort (Splay)

题意:将一列数字排序  排序规则是  每次找到最小值的位置loc  将1~loc所有数字颠倒  然后删掉第一位  直到排好序  排序要求是稳定的. 析:直接用splay来维护最小值,然后插入删除即可. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include

hdu 3998 Sequence LIS+最大流

题意:给定一个序列,求最长上升子序长度以及有多少组,每个元素只能用一次. 思路:先求LIS,记为num,求出以每个点为末尾的最长子序列长度.窝们将每个点点拆成i和i',i --> i' 容量为1,源点连接d[ i ]=1的点,容 量为1,汇点连接d[ i ]=num的点,容量为1.对于j<i, a[ j ] < a[ i ],d[ i ] = d[ j ] + 1的情况,j' --> i 连一条容量为1的边,跑最大流即可.详见代码: /***********************

hdu 5071 Chat(模拟|Splay)

Chat Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 571    Accepted Submission(s): 136 Problem Description As everyone knows, DRD has no girlfriends. But as everyone also knows, DRD's friend