Problem

给你n个数A1~An,每次将i插入第Ai位后,最后输出每次插入后这个数列的最长上升子序列

Solution

这道题非常的妙。首先如果新加入的这个数构成了最长上升子序列,由于在它插入之前都是比它小的数,所以就是最后这个序列这个位置的最长上升子序列。

如果不是最长的,只需要和前面那个数插入构成的最长上升子序列长度取max。

构造最后的序列长度可以用Treap维护。

Notice

插入点时,不用记录是第几个数,因为Treap新建节点的顺序就是插入的顺序。

Code

非旋转Treap

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. using namespace std;
  8. #define sqz main
  9. #define ll long long
  10. #define reg register int
  11. #define rep(i, a, b) for (reg i = a; i <= b; i++)
  12. #define per(i, a, b) for (reg i = a; i >= b; i--)
  13. #define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
  14. const int INF = 1e9, N = 100000;
  15. const double eps = 1e-6, phi = acos(-1.0);
  16. ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
  17. ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  18. if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
  19. void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
  20. int point = 0, root, f[N + 5], g[N + 5], T[N + 5], now = 0;
  21. struct node
  22. {
  23. int Val[N + 5], Level[N + 5], Size[N + 5], Son[2][N + 5];
  24. inline void up(int u)
  25. {
  26. Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + 1;
  27. }
  28. int Newnode(int v)
  29. {
  30. int u = ++point;
  31. Val[u] = v, Level[u] = rand();
  32. Son[0][u] = Son[1][u] = 0, Size[u] = 1;
  33. return u;
  34. }
  35. int Merge(int X, int Y)
  36. {
  37. if (X * Y == 0) return X + Y;
  38. if (Level[X] < Level[Y])
  39. {
  40. Son[1][X] = Merge(Son[1][X], Y);
  41. up(X); return X;
  42. }
  43. else
  44. {
  45. Son[0][Y] = Merge(X, Son[0][Y]);
  46. up(Y); return Y;
  47. }
  48. }
  49. void Split(int u, int t, int &x, int &y)
  50. {
  51. if (!u)
  52. {
  53. x = y = 0;
  54. return;
  55. }
  56. if (Size[Son[0][u]] < t) x = u, Split(Son[1][u], t - Size[Son[0][u]] - 1, Son[1][u], y);
  57. else y = u, Split(Son[0][u], t, x, Son[0][u]);
  58. up(u);
  59. }
  60. void Build(int l, int r)
  61. {
  62. int last, u, s[N + 5], top = 0;
  63. rep(i, l, r)
  64. {
  65. int u = Newnode(T[i]);
  66. last = 0;
  67. while (top && Level[s[top]] > Level[u])
  68. {
  69. up(s[top]);
  70. last = s[top];
  71. s[top--] = 0;
  72. }
  73. if (top) Son[1][s[top]] = u;
  74. Son[0][u] = last;
  75. s[++top] = u;
  76. }
  77. while (top) up(s[top--]);
  78. root = s[1];
  79. }
  80. int Find_rank(int v)
  81. {
  82. int x, y, t;
  83. Split(root, v - 1, x, y);
  84. t = Size[x];
  85. root = Merge(x, y);
  86. return t + 1;
  87. }
  88. int Find_num(int u, int v)
  89. {
  90. if (!u) return 0;
  91. if (v <= Size[Son[0][u]]) return Find_num(Son[0][u], v);
  92. else if (v <= Size[Son[0][u]] + 1) return u;
  93. else return Find_num(Son[1][u], v - Size[Son[0][u]] - 1);
  94. }
  95. void Insert(int v)
  96. {
  97. int t = Newnode(v), x, y;
  98. Split(root, v, x, y);
  99. root = Merge(Merge(x, t), y);
  100. }
  101. void Out(int u)
  102. {
  103. if (!u) return;
  104. Out(Son[0][u]);
  105. T[++now] = u;
  106. Out(Son[1][u]);
  107. }
  108. }Treap;
  109. int sqz()
  110. {
  111. int n = read();
  112. rep(i, 1, n)
  113. {
  114. int x = read();
  115. Treap.Insert(x);
  116. }
  117. Treap.Out(root);
  118. g[0] = -1, f[0] = 1;
  119. int len = 0;
  120. rep(i, 1, n)
  121. {
  122. int t = lower_bound(g, g + len + 1, T[i]) - g;
  123. f[T[i]] = t;
  124. if (t == len + 1) g[++len] = T[i];
  125. else g[t] = T[i];
  126. }
  127. rep(i, 1, n)
  128. {
  129. f[i] = max(f[i - 1], f[i]);
  130. printf("%d\n", f[i]);
  131. }
  132. return 0;
  133. }

旋转Treap

  1. #include<cmath>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<iostream>
  6. #include<algorithm>
  7. using namespace std;
  8. #define sqz main
  9. #define ll long long
  10. #define reg register int
  11. #define rep(i, a, b) for (reg i = a; i <= b; i++)
  12. #define per(i, a, b) for (reg i = a; i >= b; i--)
  13. #define travel(i, u) for (reg i = head[u]; i; i = edge[i].next)
  14. const int INF = 1e9, N = 100000;
  15. const double eps = 1e-6, phi = acos(-1.0);
  16. ll mod(ll a, ll b) {if (a >= b || a < 0) a %= b; if (a < 0) a += b; return a;}
  17. ll read(){ ll x = 0; int zf = 1; char ch; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  18. if (ch == '-') zf = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;}
  19. void write(ll y) { if (y < 0) putchar('-'), y = -y; if (y > 9) write(y / 10); putchar(y % 10 + '0');}
  20. int point = 0, root, f[N + 5], g[N + 5], T[N + 5], now = 0;
  21. struct node
  22. {
  23. int Val[N + 5], Level[N + 5], Size[N + 5], Son[2][N + 5];
  24. inline void up(int u)
  25. {
  26. Size[u] = Size[Son[0][u]] + Size[Son[1][u]] + 1;
  27. }
  28. inline void Newnode(int &u, int v)
  29. {
  30. u = ++point;
  31. Level[u] = rand(), Val[u] = v;
  32. Size[u] = 1, Son[0][u] = Son[1][u] = 0;
  33. }
  34. inline void Lturn(int &x)
  35. {
  36. int y = Son[1][x]; Son[1][x] = Son[0][y], Son[0][y] = x;
  37. Size[y] = Size[x]; up(x); x = y;
  38. }
  39. inline void Rturn(int &x)
  40. {
  41. int y = Son[0][x]; Son[0][x] = Son[1][y], Son[1][y] = x;
  42. Size[y] = Size[x]; up(x); x = y;
  43. }
  44. void Insert(int &u, int t)
  45. {
  46. if (u == 0)
  47. {
  48. Newnode(u, t);
  49. return;
  50. }
  51. Size[u]++;
  52. if (Size[Son[0][u]] >= t)
  53. {
  54. Insert(Son[0][u], t);
  55. if (Level[Son[0][u]] < Level[u]) Rturn(u);
  56. }
  57. else
  58. {
  59. Insert(Son[1][u], t - Size[Son[0][u]] - 1);
  60. if (Level[Son[1][u]] < Level[u]) Lturn(u);
  61. }
  62. }
  63. int Find_num(int u, int t)
  64. {
  65. if (!u) return 0;
  66. if (t <= Size[Son[0][u]]) return Find_num(Son[0][u], t);
  67. else if (t <= Size[Son[0][u]] + 1) return Val[u];
  68. else return Find_num(Son[1][u], t - Size[Son[0][u]] - 1);
  69. }
  70. void Out(int u)
  71. {
  72. if (!u) return;
  73. Out(Son[0][u]);
  74. T[++now] = u;
  75. Out(Son[1][u]);
  76. }
  77. }Treap;
  78. int sqz()
  79. {
  80. int n = read();
  81. rep(i, 1, n)
  82. {
  83. int x = read();
  84. Treap.Insert(root, x);
  85. }
  86. Treap.Out(root);
  87. g[0] = -1, f[0] = 1;
  88. int len = 0;
  89. rep(i, 1, n)
  90. {
  91. int t = lower_bound(g, g + len + 1, T[i]) - g;
  92. f[T[i]] = t;
  93. if (t == len + 1) g[++len] = T[i];
  94. else g[t] = T[i];
  95. }
  96. rep(i, 1, n)
  97. {
  98. f[i] = max(f[i - 1], f[i]);
  99. printf("%d\n", f[i]);
  100. }
  101. return 0;
  102. }

[BZOJ3173]最长上升子序列的更多相关文章

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

    最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...

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

    [BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...

  3. 【LG4309】【BZOJ3173】[TJOI2013]最长上升子序列

    [LG4309][BZOJ3173][TJOI2013]最长上升子序列 题面 洛谷 BZOJ 题解 插入操作显然用平衡树就行了 然后因为后面的插入对前面的操作无影响 就直接在插入完的序列上用树状数组求 ...

  4. 【bzoj3173】最长上升子序列

    Portal --> bzoj3173 Solution 感觉自己需要智力康复qwq 首先题目给的这个序列肯定是一个\(1-n\)的排列,并且插入的顺序是从小到大 仔细思考一下会发现如果知道了最 ...

  5. BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)

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

  6. bzoj3173[Tjoi2013]最长上升子序列 平衡树+lis

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2253  Solved: 1136[Submit][S ...

  7. bzoj千题计划316:bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3173 插入的数是以递增的顺序插入的 这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某 ...

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

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

  9. bzoj3173: [Tjoi2013]最长上升子序列(fhqtreap)

    这题用fhqtreap可以在线. fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影 ...

随机推荐

  1. SuperMap 二维地图和三维场景弹窗窗口大小控制

    注:此处所说的弹窗窗口,主要指的是那些弹窗窗口中嵌入iframe,包含信息页面的窗口大小控制. 1.首先来了解下 SuperMap 示例中的处理方案 二维的处理方式 //初始化Anchored类 po ...

  2. mui 引导页

    引导页制作 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <met ...

  3. 有效利用1 on 1

    2019-01-08 16:32:13 感觉1 on 1是浪费时间? 感觉1 on 1时没啥好说? 感觉老板总是不想1 on 1? 怎样才能 升职加薪? 一切都从有效的1 on 1开始!! 什么是1 ...

  4. reactiveCocoa使用

    @代理 简介:使用RACSubject信号替换 控制器2的操作: <1在头文件定义一个信号: @property (nonatomic, strong) RACSubject *delegate ...

  5. ubuntu无法关机,卡死

    (1)第一种方法(可行,但开关机出现命令行代码) $ sudo vim /etc/default/grub 将GRUB_CMDLINE_LINUX_DEFAULT="quiet splash ...

  6. C语言流控制命令的总结

    C语言流控制命令的总结 基本概念: C语言中,自顶向下的的代码的流程叫做程序流. 能够改变程序流顺序的语句叫做流控制命令. 我为什么要写这篇文章 在学习C语言的过程中,经常会用到条件语句和循环语句这些 ...

  7. LeetCode--292--Nim游戏

    问题描述: 你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头. 拿掉最后一块石头的人就是获胜者.你作为先手. 你们是聪明人,每一步都是最优解. 编写一个函 ...

  8. python记录_day10 动态传参 命名空间 作用域

    一.动态传参 动态传参用到 *args 和 **kwargs ,*号表示接收位置参数,args是参数名:**表示接收关键字参数,kwargs是参数名 def chi(*food): print(foo ...

  9. Homebrew 安装mysql

    在mac上安装软件,无疑安装一个brew是个很好的选择,关于brew是什么,怎么安装建议去brew官网查看, 附上地址:brew官网  还有一篇博文 http://www.cnblogs.com/xd ...

  10. oracle 如何创建只有查询权限的用户

    .create user userName identified by password; .grant select any table to userName; --授予查询任何表 .grant ...