[TJOI]2013 最长上升子序列

这个题据说是Splay,或者说是平衡树的模板题,但是我还是不会做……唉……

Description

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

输入格式:

第一行一个整数N,表示我们要将1N插入序列中。

接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk (0<=Xk<=k1,1<=k<=N)

输出格式:

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

HalfSolution

首先很明显的是,我们的权值就是i,在插入的时候我们就按照他的实际位置插入,然后找它之前的第一个点,把当前节点变成找到的节点右儿子即可。

那么现在有一个问题,我们在维护完这个序列之后,如何确定它的LIS呢?听rqy说,是可以在每次插入的时候在线输出的,但是我觉得完全可以把它处理成一个离线问题,最后复制Splay的中序遍历,然后再对这个数组nlogn求一遍LIS

但我实在不想写了,现在身心俱疲。

于是我就等着什么时候可以学会在线输出的算法,再把这个题A掉吧。

他们都在复习中考数学,初中奥数,或者说是预习,因为要考推荐生了。而我现在还在和这个题鏖战……不知道推荐生能不能过……唉……

我选择Waiting

#include<iostream>
#include<cstdio>
#define MAXN 100010
#define il inline 
using namespace std;
struct tree{
	int maxf,v,sub,son[2],f,pos;
}s[MAXN];
bool w;
int f[MAXN],n,root,wz,fnow,now,ffnow,temp[MAXN],base[MAXN];
il void update(int x){
	if(x){
		s[x].sub=1;
		if(s[x].son[0])s[x].sub+=s[s[x].son[0]].sub;
		if(s[x].son[1])s[x].sub+=s[s[x].son[1]].sub;
	}
}

il void push_up(int x){
	maxf=max(f[x])
}

il bool which(int x){
	return x==s[s[x].f].son[1];
}
il void rotate(int x){
	fnow=s[x].f,ffnow=s[fnow].f;
	w=which(x);
	s[fnow].son[w]=s[x].son[w^1];
	s[s[x].son[w^1]].f=fnow;
	s[x].f=ffnow;
	if(ffnow){
		s[ffnow].son[fnow==s[ffnow].son[1]]=x;
	}
	s[x].son[w^1]=fnow;
	s[fnow].f=x;
	update(fnow);
	update(x);
}
il void splay(int x,int goal){
	for(int qwq;(qwq=s[x].f)!=goal;rotate(x)){
		if(s[qwq].f!=goal){
			rotate(which(x)==which(qwq)?qwq:x);
		}
	}
	if(!goal){
		root=x;
	}
}
il void insert(int pos,int x){
	if(!root){
		wz++;
		s[wz].son[1]=s[wz].son[0]=s[wz].f=0;
		s[wz].sub=1;
		s[wz].v=x;
		return ;
	}
	if(!pos){
		wz++;
		s[wz].son[1]=root;
		s[wz].f=s[wz].son[0]=0;
		s[wz].v=x;
		root=wz;
		update(wz);
		return ;
	}
    int now=root;
    while(1){
        if(s[now].son[0]&&x<=s[s[now].son[0]].sub)
        now=s[now].son[0];
        else {
            int temp=(s[now].son[0]?s[s[now].son[0].sub]:0)+1;
            if(x<=temp)break;
            x-=temp;
            now=s[now].son[1];
        }
    }
    wz++;
    s[wz].son[1]=s[now].son[1];
    s[s[now].son[1]].f=wz;
	s[now].son[1]=wz;
    s[wz].f=now;
    update(wz);
    update(now);
    pushup(wz);
    pushup(now);
    splay(wz);
    cout<<s[wz].maxf<<endl;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>temp[i];
	}	
	for(int i=1;i<=n;i++)}{
		insert(temp[i],i);
	}
}
posted @   皎月半洒花  阅读(220)  评论(0编辑  收藏  举报
编辑推荐:
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
· Tinyfox 简易教程-1:Hello World!
点击右上角即可分享
微信分享提示