bzoj3173

Description

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

Input

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

Output

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

因为后面插入的数一定比前面的大, 所以更后插入的对当前的答案没有任何影响,所以预处理出每个数的最终位置,然后动态规划即可。

时间复杂度O(nlogn)

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string>
 4 #include<string.h>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<math.h>
 9 #include<vector>
10 #include<map>
11 #include<set>
12 #define il inline
13 #define re register
14 using namespace std;
15 const int N=1000001;
16 int l[N],r[N],rnd[N],siz[N],v[N],s[N],cnt,now,root,n,ans[N],g;
17 il void update(re int k){
18     siz[k]=siz[l[k]]+siz[r[k]]+1;
19 }
20 il void rturn(re int &k){
21     int t=l[k];l[k]=r[t];r[t]=k;update(k);update(t);k=t;
22 }
23 il void lturn(re int &k){
24     int t=r[k];r[k]=l[t];l[t]=k;update(k);update(t);k=t;
25 }
26 il void insert(re int &k,re int rank){
27     if(!k){
28         k=(++cnt);rnd[k]=rand();siz[k]=1;return;
29     }
30     siz[k]++;
31     if(siz[l[k]]<rank){
32         insert(r[k],rank-siz[l[k]]-1);
33         if(rnd[r[k]]<rnd[k]) lturn(k);
34     }
35     else{
36         insert(l[k],rank);
37         if(rnd[l[k]]<rnd[k]) rturn(k);
38     }
39 }
40 il int read(){
41     re int hs=0;re char c=getchar();
42     while(!isdigit(c)) c=getchar();
43     while(isdigit(c)){
44         hs=(hs<<3)+(hs<<1)+c-‘0‘;
45         c=getchar();
46     }
47     return hs;
48 }
49 il void dfs(re int k){
50     if(!k) return;
51     dfs(l[k]);
52     v[++now]=k;
53     dfs(r[k]);
54 }
55 int main(){
56     memset(s,127,sizeof(s));s[0]=-1000000000;n=read();
57     for(re int i=1,x;i<=n;i++){
58         x=read();insert(root,x);
59     }
60     dfs(root);
61     for(re int i=1,t;i<=n;i++){
62         t=upper_bound(s,s+g+1,v[i])-s;
63         if(s[t-1]<=v[i]){
64             s[t]=min(s[t],v[i]);
65             ans[v[i]]=t;
66             g=max(g,t);
67         }
68     }
69     for(re int i=1;i<=n;i++){
70         ans[i]=max(ans[i-1],ans[i]);
71         printf("%d\n",ans[i]);
72     }
73     return 0;
74 }
时间: 2024-10-13 21:03:10

bzoj3173的相关文章

bzoj3173 最长上升子序列 树状数组

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3173 题意:向序列中动态插入$1~n$排列元素,求出插入每个元素后最长上升子序列长度. 如Claris所言,面对这种数据结构,必有高论.如果只想着数据结构,我们可以通过平衡树动态维护序列,同时使用树状数组计算最长上升子序列. 但是我们不是猩猩不是数据结构狂人,我们毕竟还是要本着能不上树就不上树能少用数据结构就少用的原则来设计算法的. 重新考虑这个题目.本题没有要求强制在线,于是我们把整个操作

[bzoj3173]最长上升子序列_非旋转Treap

最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为空. 想法:显然,我们发现,我每次加入的数一定是当前序列中最大的,所以,刚刚加入的i,要么是当前序列中LIS的结尾,要么不属于LIS.根据这个性质,我们想到:在Treap中维护这样的性质,就是维护每个数加入节点的编号.然后,我们更新新节点的方式就是它的左子树和右子树的LIS取最大+1.其实最重要的就是如何加入

【bzoj3173】最长上升子序列

Portal --> bzoj3173 Solution 感觉自己需要智力康复qwq 首先题目给的这个序列肯定是一个\(1-n\)的排列,并且插入的顺序是从小到大 仔细思考一下会发现如果知道了最终的序列,问题就比较好解决了,这里提供一种用线段树的做法: 如果知道了最终的序列,记数字\(i\)在该序列中的位置为\(loc[i]\),那么我们按照\(i\)从小到大的顺序,查询结尾在\([1,loc[i])\)的这段位置中的最长上升子序列的最大值\(mx\),并将\(mx+1\)作为以\(loc[i]

[BZOJ3173][Tjoi2013]最长上升子序列

试题描述 给定一个序列,初始为空.现在我们将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 数据规模及约定 100%的数据 n<=

bzoj3173 Splay 维护前缀中的最大值

大致题意: 有一个空序列,依次插入1~N到该序列中,每次制定插入的位置,每次插入完成返回当前序列的LIS的长度. 题解: 设dp[i]表示 前缀1~i的最长上升子序列的长度. 因为是按照递增顺序插入的,所以dp[i] = max{ dp[j] | j<i },答案 ans=max{ dp[i] | i in [1,len] } 因为要支持动态插入,所以要用BST来做,每个节点代表一个位置(即树的中序遍历就是该序列),每个节点维护dp[i]和 dpmax[i] = max{ dp[i] | i i

BZOJ3173: [Tjoi2013]最长上升子序列 Treap 平衡树

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 Outp

bzoj3173 最长上升自序列 块状链表

题意:动态插入数,求每次插完后的最长上升自序列长度.(N<=100000) 动态插入部分 块状链表 块状链表: split:分裂 O(sqrt(n)) merge:合并 O(sqrt(n)) insert:插入 具体做法是找到对应的块O(sqrt(n)),在该块内找到对应的点O(sqrt(n))split,merge(first,now),merge(now,second) maintain:整理 当两个相邻块sz和大于sqrt(n)时,merge,据说合并次数少,所以maintain操作也是O

【bzoj3173】[Tjoi2013]最长上升子序列

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 Outp

bzoj刷题(shui)记录

放假刷了一个月的水题,集中写一下题解吧. bzoj1858:线段树随便维护一下. code bzoj2705:莫比乌斯反演裸题. code bzoj1202:并查集,但是我写了一种跟floyd很像的奇怪的东西. code bzoj1072:暴力. bzoj2431:dp f[i][j]=sum(f[i-1],[k]) code bzoj3505:组合数学. code bzoj1058:两棵平衡树. code bzoj1922:维护两个距离,然后更新答案. code bzoj1009:之前写过题解