BZOJ3173:[TJOI2013]最长上升子序列(Splay)

本文介绍了一种解决最长上升子序列问题的算法,该算法在动态插入元素时能够实时更新最长上升子序列的长度。通过使用Splay树进行维护,确保了在序列中插入新元素时,能够高效地计算出新的最长上升子序列长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

Solution

设$f[i]$表示以$i$数字为结尾的最长上升子序列长度。

可以发现插入一个数的时候只有当前这个数的$f$会变化,也就是当前这个数前面一段的$max(f)+1$。

用$Splay$维护一下就好了。

Code

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define N (100009)
 5 using namespace std;
 6 
 7 int n,m,p,ans,Root;
 8 int Father[N],Son[N][2],f[N],Max[N],Size[N];
 9 
10 inline int read()
11 {
12     int x=0,w=1; char c=getchar();
13     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
14     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
15     return x*w;
16 }
17 
18 int Get(int x)
19 {
20     return Son[Father[x]][1]==x;
21 }
22 
23 void Pushup(int x)
24 {
25     Max[x]=f[x];
26     if (Son[x][0]) Max[x]=max(Max[x],Max[Son[x][0]]);
27     if (Son[x][1]) Max[x]=max(Max[x],Max[Son[x][1]]);
28     Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
29 }
30 
31 void Rotate(int x)
32 {
33     int wh=Get(x);
34     int fa=Father[x],fafa=Father[fa];
35     if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
36     Father[fa]=x; Son[fa][wh]=Son[x][wh^1];
37     if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
38     Father[x]=fafa; Son[x][wh^1]=fa;
39     Pushup(fa); Pushup(x);
40 }
41 
42 void Splay(int x,int tar)
43 {
44     for (int fa; (fa=Father[x])!=tar; Rotate(x))
45         if (Father[fa]!=tar) Rotate(Get(fa)==Get(x)?fa:x);
46     if (!tar) Root=x;
47 }
48 
49 int Next(int now)
50 {
51     if (!Son[now][1]) return now;
52     now=Son[now][1];
53     while (Son[now][0]) now=Son[now][0];
54     return now;
55 }
56 
57 int Findkth(int x)
58 {
59     int now=Root;
60     while (1)
61         if (x<=Size[Son[now][0]]) now=Son[now][0];
62         else
63         {
64             x-=Size[Son[now][0]];
65             if (x==1) {Splay(now,0); return now;}
66             x--; now=Son[now][1];
67         }
68 }
69 
70 int main()
71 {
72     n=read();
73     Max[1]=Max[n+2]=f[1]=f[n+2]=-2e9;
74     Father[n+2]=1; Son[1][1]=n+2;
75     for (int i=2; i<=n+2; ++i) Size[i]=1;
76     Size[1]=2; Root=1;
77     for (int i=2; i<=n+1; ++i)
78     {
79         p=read(); p=Findkth(p+1);
80         int nxt=Next(Root);
81         
82         Splay(1,0);
83         if (nxt!=1) Splay(nxt,1);
84         f[i]=Max[Son[nxt][0]]+1;
85         ans=max(ans,f[i]);
86         printf("%d\n",ans);
87         
88         Splay(p,0);
89         if (nxt!=p) Splay(nxt,p);
90         Father[i]=nxt; Son[nxt][0]=i;
91         Max[i]=f[i];
92         Splay(i,0);
93     }
94 }

 

转载于:https://www.cnblogs.com/refun/p/10362312.html

内容概要:本文深入解析了扣子COZE AI编程及其详细应用代码案例,旨在帮助读者理解新一代低门槛智能体开发范式。文章从五个维度展开:关键概念、核心技巧、典型应用场景、详细代码案例分析以及未来发展趋势。首先介绍了扣子COZE的核心概念,如Bot、Workflow、Plugin、Memory和Knowledge。接着分享了意图识别、函数调用链、动态Prompt、渐进式发布及监控可观测等核心技巧。然后列举了企业内部智能客服、电商导购助手、教育领域AI助教和金融行业合规质检等应用场景。最后,通过构建“会议纪要智能助手”的详细代码案例,展示了从需求描述、技术方案、Workflow节点拆解到调试与上线的全过程,并展望了多智能体协作、本地私有部署、Agent2Agent协议、边缘计算插件和实时RAG等未来发展方向。; 适合人群:对AI编程感兴趣的开发者,尤其是希望快速落地AI产品的技术人员。; 使用场景及目标:①学习如何使用扣子COZE构建生产级智能体;②掌握智能体实例、自动化流程、扩展能力和知识库的使用方法;③通过实际案例理解如何实现会议纪要智能助手的功能,包括触发器设置、下载节点、LLM节点Prompt设计、Code节点处理和邮件节点配置。; 阅读建议:本文不仅提供了理论知识,还包含了详细的代码案例,建议读者结合实际业务需求进行实践,逐步掌握扣子COZE的各项功能,并关注其未来的发展趋势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值