这个题感觉比较简单,但却比较容易想残。。

我不会用树状数组求这个原排列,于是我只好用线段树。。。毕竟 Gromah 果弱马。

我们可以直接依次求出原排列的元素,每次找到最小并且最靠右的那个元素,假设这是第 $i$ 次找的,那么这就是原排列的第 $i$ 项,然后我们就把这个元素删去(变成很大的数),再把这个数以左的数都加 1,进行下一轮。

然后就是裸的最长上升子序列啦~~~

时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define N 100000 + 5
  5. #define M 262144 + 5
  6. #define ls(x) x << 1
  7. #define rs(x) x << 1 | 1
  8.  
  9. int n, Pos[N], A[N], T[N], F[N];
  10.  
  11. struct Segment_Tree
  12. {
  13. int Min, delta;
  14. }h[M];
  15.  
  16. inline void Build(int x, int l, int r)
  17. {
  18. if (l == r)
  19. {
  20. h[x].Min = Pos[l];
  21. return ;
  22. }
  23. int mid = l + r >> ;
  24. Build(ls(x), l, mid);
  25. Build(rs(x), mid + , r);
  26. h[x].Min = min(h[ls(x)].Min, h[rs(x)].Min);
  27. }
  28.  
  29. inline void apply(int x, int d)
  30. {
  31. h[x].Min += d, h[x].delta += d;
  32. }
  33.  
  34. inline void push(int x)
  35. {
  36. if (h[x].delta)
  37. {
  38. apply(ls(x), h[x].delta);
  39. apply(rs(x), h[x].delta);
  40. h[x].delta = ;
  41. }
  42. }
  43.  
  44. inline void Modify(int x, int l, int r, int s, int t, int d)
  45. {
  46. if (l == s && r == t)
  47. {
  48. apply(x, d);
  49. return ;
  50. }
  51. push(x);
  52. int mid = l + r >> ;
  53. if (t <= mid) Modify(ls(x), l, mid, s, t, d);
  54. else if (s > mid) Modify(rs(x), mid + , r, s, t, d);
  55. else Modify(ls(x), l, mid, s, mid, d), Modify(rs(x), mid + , r, mid + , t, d);
  56. h[x].Min = min(h[ls(x)].Min, h[rs(x)].Min);
  57. }
  58.  
  59. inline int Query(int x, int l, int r)
  60. {
  61. if (l == r) return l;
  62. int mid = l + r >> ;
  63. if (h[rs(x)].Min <= h[ls(x)].Min)
  64. return Query(rs(x), mid + , r);
  65. else return Query(ls(x), l, mid);
  66. }
  67.  
  68. int main()
  69. {
  70. #ifndef ONLINE_JUDGE
  71. freopen("3173.in", "r", stdin);
  72. freopen("3173.out", "w", stdout);
  73. #endif
  74.  
  75. scanf("%d", &n);
  76. for (int i = ; i <= n; i ++)
  77. scanf("%d", Pos + i);
  78. Build(, , n);
  79. for (int i = ; i <= n; i ++)
  80. {
  81. int t = Query(, , n);
  82. Modify(, , n, , t, );
  83. Modify(, , n, t, t, n);
  84. if (!T[] || T[T[]] < t)
  85. {
  86. T[++ T[]] = t;
  87. F[t] = T[];
  88. }
  89. else
  90. {
  91. int x = lower_bound(T + , T + T[] + , t) - T;
  92. T[x] = t;
  93. F[t] = x;
  94. }
  95. }
  96. for (int i = , Max = ; i <= n; i ++)
  97. {
  98. Max = Max > F[i] ? Max : F[i];
  99. printf("%d\n", Max);
  100. }
  101.  
  102. #ifndef ONLINE_JUDGE
  103. fclose(stdin);
  104. fclose(stdout);
  105. #endif
  106. return ;
  107. }

3173_Gromah

BZOJ 3173 [Tjoi2013] 最长上升子序列 解题报告的更多相关文章

  1. BZOJ 3173: [Tjoi2013]最长上升子序列

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1524  Solved: 797[Submit][St ...

  2. Bzoj 3173: [Tjoi2013]最长上升子序列 平衡树,Treap,二分,树的序遍历

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1183  Solved: 610[Submit][St ...

  3. BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )

    因为是从1~n插入的, 慢插入的对之前的没有影响, 所以我们可以用平衡树维护, 弄出最后的序列然后跑LIS就OK了 O(nlogn) --------------------------------- ...

  4. BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1613  Solved: 839[Submit][St ...

  5. bzoj 3173 [Tjoi2013]最长上升子序列 (treap模拟+lis)

    [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2213  Solved: 1119[Submit][Status] ...

  6. BZOJ 3173: [Tjoi2013]最长上升子序列 (线段树+BIT)

    先用线段树预处理出每个数最终的位置.然后用BIT维护最长上升子序列就行了. 用线段树O(nlogn)O(nlogn)O(nlogn)预处理就直接倒着做,每次删去对应位置的数.具体看代码 CODE #i ...

  7. bzoj 3173: [Tjoi2013]最长上升子序列【dp+线段树】

    我也不知道为什么把题看成以插入点为结尾的最长生生子序列--还WA了好几次 先把这个序列最后的样子求出来,具体就是倒着做,用线段树维护点数,最开始所有点都是1,然后线段树上二分找到当前数的位置,把这个点 ...

  8. BZOJ 3173: [Tjoi2013]最长上升子序列 Splay

    一眼切~ 重点是按照 $1$~$n$ 的顺序插入每一个数,这样的话就简单了. #include <cstdio> #include <algorithm> #define N ...

  9. 3173: [Tjoi2013]最长上升子序列

    原题:http://www.lydsy.com/JudgeOnline/problem.php?id=3173 题解:促使我写这题的动力是,为什么百度遍地是Treap,黑人问号??? 这题可以用线段树 ...

随机推荐

  1. C#数组比较取值

    string strs = string.Empty;            string[] strArray1 = { "a", "b", "c& ...

  2. linux中sed用法

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为:         sed ...

  3. 把CheckedListBoxControl设置为单选框

    private void chkControl_ItemChecking(object sender, DevExpress.XtraEditors.Controls.ItemCheckingEven ...

  4. 设置win7任务栏显示标题,而不显示缩略图

    win7系统的任务栏可以显示桌面缩略图,这是非常好的一个功能,但是有时候我们希望只显示标题,如下所示 怎样设置呢?只要在桌面上的计算机图标上面“右键”,选择“属性”,在弹出的窗口选择“高级系统设置”, ...

  5. CSS 元素垂直居中的 6种方法

    利用CSS进行元素的水平居中,比较简单,行级元素设置其父元素的text-align center,块级元素设置其本身的left 和 right margins为auto即可.本文收集了六种利用css进 ...

  6. block的动态传值例子

    /*  写一个block传值  ,让两个数进行相除和相乘,在运行时动态决定采用哪种计算方式 */ #import <Foundation/Foundation.h> int main(in ...

  7. Unity连接本地数据库sqlite

    首先要创建一个sqlite的数据库,记住文件地址,拷贝到Assets目录下,创建的数据库文件后缀为.sqlite.具体创建方法百度sqlite 然后百度Mono.Data.Sqlite,这是一个dll ...

  8. JavaScript--面向对象与原型(15)

    // ECMAScript有两种开发模式:1.函数式(过程化);2.面向对象(OOP); 一 创建对象 1.普通的创建对象 1 // 创建一个对象,然后给这个对象新的属性和方法; 2 var box ...

  9. 有道单词本添加js实现自动阅读单词

    个人比较习惯使用有道,使用了一段时间,背单词的时候很不方便   而有道单词客户Duan没有自动阅读的功能,  本菜用强大的js实现了简单的自动下一个单词的功能, 方法:第一步打开有道路径下的" ...

  10. 3月31日学习笔记(CSS基础)

    背景属性 文本属性 direction 属性影响块级元素中文本的书写方向.表中列布局的方向.内容水平填充其元素框的方向.以及两端对齐元素中最后一行的位置. 注释:对于行内元素,只有当 unicode- ...