zoukankan      html  css  js  c++  java
  • 洛谷 P4093: bzoj 4553: [HEOI2016/TJOI2016]序列

    题目传送门:洛谷P4093

    题意简述:

    给定一个长度为 (n) 的序列 (a)。

    同时这个序列还可能发生变化,每一种变化 ((x_i,y_i)) 对应着 (a_{x_i}) 可能变成 (y_i)。

    不会同时发生两种变化。

    需要找出一个最长的子序列,使得这个子序列在任意一种变化下都是不降的。

    只需要求出这个子序列的长度即可。

    注意:可以不发生任何变化。

    题解:

    记 (f[i]) 为以第 (i) 项结尾的子序列最长长度。

    则有转移:(f[i]=max_{j<i}(f[j])+1),同时还要满足 (maxval_jle a_i) 和 (a_jle minval_i)。

    按照项从小到大转移,形成了天然的时间顺序,同时还要满足两个偏序限制。
    其中 (maxval_i) 表示第 (i) 项最大能变成的值,(minval_i) 表示第 (i) 项最小能变成的值。

    算上时间顺序,这是一个三维偏序问题,用 CDQ 分治 + 数据结构(我用了树状数组)就能解决。

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 const int MN = 100005;
     6 const int MC = 100000;
     7 
     8 int N, M;
     9 int A[MN], Mx[MN], Mn[MN];
    10 int f[MN], Ans;
    11 int p[MN];
    12 inline bool cmp1(int i, int j) { return Mx[i] < Mx[j]; }
    13 inline bool cmp2(int i, int j) { return A[i] < A[j]; }
    14 
    15 int B[MN];
    16 inline void Ins(int i, int x) { for (; i <= MC; i += i & -i) B[i] = max(B[i], x); }
    17 inline void Clr(int i) { for (; i <= MC; i += i & -i) B[i] = 0; }
    18 inline int Qur(int i) { int A = 0; for (; i; i -= i & -i) A = max(A, B[i]); return A;}
    19 
    20 void CDQ(int lb, int rb) {
    21     if (lb == rb) {
    22         f[lb] = max(f[lb], 1);
    23         return;
    24     }
    25     int mid = lb + rb >> 1;
    26     CDQ(lb, mid);
    27     for (int i = lb; i <= rb; ++i)
    28         p[i] = i;
    29     sort(p + lb, p + mid + 1, cmp1);
    30     sort(p + mid + 1, p + rb + 1, cmp2);
    31     int j = lb;
    32     for (int i = mid + 1; i <= rb; ++i) {
    33         while (j <= mid && Mx[p[j]] <= A[p[i]]) {
    34             Ins(A[p[j]], f[p[j]]);
    35             ++j;
    36         }
    37         f[p[i]] = max(f[p[i]], Qur(Mn[p[i]]) + 1);
    38     }
    39     for (int i = lb; i <= mid; ++i)
    40         Clr(A[i]);
    41     CDQ(mid + 1, rb);
    42 }
    43 
    44 int main() {
    45     int x, y;
    46     scanf("%d%d", &N, &M);
    47     for (int i = 1; i <= N; ++i)
    48         scanf("%d", &A[i]),
    49         Mx[i] = Mn[i] = A[i];
    50     for (int i = 1; i <= M; ++i)
    51         scanf("%d%d", &x, &y),
    52         Mx[x] = max(Mx[x], y),
    53         Mn[x] = min(Mn[x], y);
    54     CDQ(1, N);
    55     for (int i = 1; i <= N; ++i)
    56         Ans = max(Ans, f[i]);
    57     printf("%d
    ", Ans);
    58     return 0;
    59 }
  • 相关阅读:
    hdu-1862 EXCEL排序
    hdu-1754 I Hate It
    hdu-1538 A Puzzle for Pirates
    在Window下安装Linux (ubuntu-16.04.2)
    Python爬虫--简单的单词查询
    Linux下MySQL在知道密码的情况下修改密码
    Linux下忘记MySQL密码的解决方法和输入mysqld_safe --skip-grant-tables &后无法进入MySQL的解决方法
    Python的下载及安装
    在Netbeans的项目中添加JDBC驱动程序
    Mac下截屏方法
  • 原文地址:https://www.cnblogs.com/PinkRabbit/p/10096763.html
Copyright © 2011-2022 走看看