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

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1524  Solved: 797
[Submit][Status][Discuss]

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

Source

 

[Submit][Status][Discuss]

分析

本来是想找Treap的练手题,考完NOIP放松一下心情的,结果看完题发现根本不用Treap……

首先,因为加入的元素是越来越大的,所以每次加入之后对于后面的元素的LIS的DP值(即以其结尾的最长上升子序列长度)不会改变,而前面的更不会改变。也就是说,最终序列的DP数组就是逐步加入的DP值了。所以只需要想方设法求出最终序列,再做一遍O(NlogN)的LIS问题即可。

求解最终的序列方法多种多样,可以用Treap暴力维护插入操作,也可以逆着推出最终的序列,我选择了后者。

对于第N个插入的元素,其插入的位置就是最终的位置。当它找到了最终位置之后,就把那个位置改为空。类似的,每个元素的最终位置,就是此时的第Xk个非空位置。这个操作用线段树维护即可轻松做到O(logN),当然也可以树状数组+二分做到O(log^2N),常数小也许跑得反而更快,(lll¬ω¬)。

代码

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define low lower_bound
  6. #define upp upper_bound
  7.  
  8. const int N = ;
  9. const int inf = 0x3f3f3f3f;
  10.  
  11. int n;
  12. int pos[N];
  13. int num[N];
  14. int ans[N];
  15. int stk[N];
  16.  
  17. struct node
  18. {
  19. int lt, rt, sum;
  20.  
  21. node (void) :
  22. lt (), rt (), sum () {};
  23. };
  24.  
  25. node tree[N << ];
  26.  
  27. void build (int p, int l, int r)
  28. {
  29. node &t = tree[p];
  30.  
  31. t.lt = l;
  32. t.rt = r;
  33.  
  34. t.sum = r - l + ;
  35.  
  36. if (l != r)
  37. {
  38. int mid = (l + r) >> ;
  39.  
  40. build (p << , l, mid);
  41. build (p << | , mid + , r);
  42. }
  43. }
  44.  
  45. void change (int p, int pos, int val)
  46. {
  47. node &t = tree[p];
  48.  
  49. if (t.lt != t.rt)
  50. {
  51. int mid = (t.lt + t.rt) >> ;
  52.  
  53. if (pos <= mid)
  54. change (p << , pos, val);
  55. else
  56. change (p << | , pos, val);
  57.  
  58. t.sum = tree[p << ].sum + tree[p << | ].sum;
  59. }
  60. else
  61. t.sum = val;
  62. }
  63.  
  64. int query (int p, int val)
  65. {
  66. node &t = tree[p];
  67.  
  68. if (t.lt != t.rt)
  69. {
  70. int tmp = tree[p << ].sum;
  71.  
  72. if (val <= tmp)
  73. return query (p << , val);
  74. else
  75. return query (p << | , val - tmp);
  76. }
  77. else
  78. return t.lt;
  79. }
  80.  
  81. signed main (void)
  82. {
  83. scanf ("%d", &n);
  84.  
  85. for (int i = ; i <= n; ++i)
  86. scanf ("%d", pos + i);
  87.  
  88. build (, , n);
  89.  
  90. for (int i = n; i >= ; --i)
  91. {
  92. int t = query (, pos[i] + );
  93. num[t] = i, change (, t, );
  94. }
  95.  
  96. memset (stk, inf, sizeof(stk));
  97.  
  98. for (int i = ; i <= n; ++i)
  99. {
  100. *low (stk, stk + i, num[i]) = num[i];
  101. ans[num[i]] = low (stk, stk + i, num[i]) - stk;
  102. }
  103.  
  104. for (int i = ; i <= n; ++i)
  105. ans[i] = max (ans[i], ans[i - ]);
  106.  
  107. for (int i = ; i <= n; ++i)
  108. printf ("%d\n", ans[i] + );
  109. }

BZOJ_3173.cpp

后记:

大概是刚考完NOIP,又要准备学考,大家的刷题兴致不高啊,居然被我轻松拿了Day榜,(*^_^*)/。

No. User Nick Name AC Submit Ratio
1 YOUSIKI ねえ、あなたは知っていますか、桜の行方の速度は秒速5センチメートル 5 6 83.333%

@Author: YouSiki

BZOJ 3173: [Tjoi2013]最长上升子序列的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 3173 [Tjoi2013] 最长上升子序列 解题报告

    这个题感觉比较简单,但却比较容易想残.. 我不会用树状数组求这个原排列,于是我只好用线段树...毕竟 Gromah 果弱马. 我们可以直接依次求出原排列的元素,每次找到最小并且最靠右的那个元素,假设这 ...

  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. IOS-利用AFNetworking监听网络状态

    网络环境检测:检测用户当前所处的网络状态 效果图 1.当蜂窝和wifi同时关闭时候  显示为不可达(AFNetworkReachabilityStatusNotReachable)状态 2.打开蜂窝移 ...

  2. 【转】mysql触发器的实战(触发器执行失败,sql会回滚吗)

    1   引言Mysql的触发器和存储过程一样,都是嵌入到mysql的一段程序.触发器是mysql5新增的功能,目前线上凤巢系统.北斗系统以及哥伦布系统使用的数据库均是mysql5.0.45版本,很多程 ...

  3. xenserver磁盘扩容扩不大问题解决

    http://www.osyunwei.com/archives/7956.html xenserver将磁盘扩大后,fdisk可以看到容量大了 但是df -h确实没大?   解决: fdisk /d ...

  4. java并发:线程同步机制之ThreadLocal

    1.简述ThreadLocal ThreadLocal实例通常作为静态的私有的(private static)字段出现在一个类中,这个类用来关联一个线程.ThreadLocal是一个线程级别的局部变量 ...

  5. 架构系列:ASP.NET 项目结构搭建

    我们头开始,从简单的单项目解决方案,逐步添加业务逻辑的约束,从应用逻辑和领域逻辑两方面考虑,从简单的单个项目逐步搭建一个多项目的解决方案.主要内容:(1)搭建应用逻辑和领域逻辑都简单的单项目 (2)为 ...

  6. Form表单提交的简要方式

    <html> <head> <meta name="viewport" content="width=device-width" ...

  7. Android开发之补间动画、XML方式定义补间动画

    四种补间动画: 1.透明: 2.缩放: 3.位移: 4.旋转: //点击按钮 实现iv 透明的效果 动画 public void click1(View v) { //1.0意味着着完全不透明 0.0 ...

  8. 最棒的10款MySQL GUI工具

    绝大多数的关系数据库都明显不同于MS Access,它们都有两个截然不同的部分:后端作为数据仓库,前端作为用于数据组件通信的用户界面.这种设计非常巧妙,它并行处理两层编程模型,将数据 层从用户界面中分 ...

  9. xml文件的生成与解析

    生成方法一:同事StringBuffer类对xml文件格式解析写入 package com.steel_rocky.xml; import android.app.Activity; import a ...

  10. PHP Apache 配置伪静态

    1.首先是开启rewrite_module(如何开启,百度搜索) 2.创建.htaccess文件(如何创建,百度搜索) 3.在.htaccess文件中打开重写服务:RewriteEngine On 4 ...