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


    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 = 100005;
      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 (0), rt (0), sum (0) {};
     23 };
     24 
     25 node tree[N << 2];
     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 + 1;
     35     
     36     if (l != r)
     37     {
     38         int mid = (l + r) >> 1;
     39         
     40         build (p << 1, l, mid);
     41         build (p << 1 | 1, mid + 1, 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) >> 1;
     52         
     53         if (pos <= mid)
     54             change (p << 1, pos, val);
     55         else
     56             change (p << 1 | 1, pos, val);
     57         
     58         t.sum = tree[p << 1].sum + tree[p << 1 | 1].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 << 1].sum;
     71         
     72         if (val <= tmp)
     73             return query (p << 1, val);
     74         else
     75             return query (p << 1 | 1, 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 = 1; i <= n; ++i)
     86         scanf ("%d", pos + i);
     87         
     88     build (1, 1, n);
     89     
     90     for (int i = n; i >= 1; --i)
     91     {
     92         int t = query (1, pos[i] + 1);
     93         num[t] = i, change (1, t, 0);
     94     }
     95         
     96     memset (stk, inf, sizeof(stk));
     97     
     98     for (int i = 1; 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 = 1; i <= n; ++i)
    105         ans[i] = max (ans[i], ans[i - 1]);
    106         
    107     for (int i = 1; i <= n; ++i)
    108         printf ("%d
    ", ans[i] + 1);
    109 }
    BZOJ_3173.cpp

    后记:

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

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

    @Author: YouSiki

  • 相关阅读:
    时空权衡之计数排序
    何时发生隐式类型转换
    常量指针与指针常量的区别
    虚函数有关面试题
    C++中数组定义及初始化
    InputStream类的available()方法
    FORK()函数
    面向对象三大基本特性,五大基本原则
    SpringMVC工作原理
    java文件的上传
  • 原文地址:https://www.cnblogs.com/yousiki/p/6087448.html
Copyright © 2020-2023  润新知