zoukankan      html  css  js  c++  java
  • BZOJ3173 [Tjoi2013]最长上升子序列

    可以称为,模拟题、、、

    我们发现,由于是从小到大插入的,所以后插入的数不会影响先插入的数的ans

    于是只要对最后的序列求一次LIS即可。

    问题就集中在如何求最后的序列:

    方法一:treap无脑模拟插入操作

    就当是treap的练手吧。。。结果RE了一版,后来突然一拍脑袋发现。。bz上不让调用time()函数。。。各种蛋疼

      1 /**************************************************************
      2     Problem: 3173
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:660 ms
      7     Memory:3936 kb
      8 ****************************************************************/
      9  
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #include <cstring>
     13 #include <algorithm>
     14  
     15 using namespace std;
     16 const int N = 100005;
     17 const int inf = 1e9;
     18  
     19 struct treap_node {
     20   treap_node *son[2];
     21   int pri, sz, v;
     22 } *null, *root, mempool[N], *cnt_treap = mempool;
     23  
     24 int n, cnt, len;
     25 int a[N], ans[N], mn[N];
     26  
     27 int read() {
     28   int x = 0;
     29   char ch = getchar();
     30   while (ch < '0' || '9' < ch)
     31     ch = getchar();
     32   while ('0' <= ch && ch <= '9')
     33     (x *= 10) += ch - '0', ch = getchar();
     34   return x;
     35 }
     36  
     37 #define Ls (p -> son[0])
     38 #define Rs (p -> son[1])
     39 #define Pri (p -> pri)
     40 #define Sz (p -> sz)
     41 #define V (p -> v)
     42 inline void treap_update(treap_node *p) {
     43   Sz = Ls -> sz + Rs -> sz + 1;
     44 }
     45  
     46 void treap_rotate(treap_node *&p, int ch) {
     47   treap_node *tmp = p -> son[ch];
     48   p -> son[ch] = tmp -> son[!ch];
     49   tmp -> son[!ch] = p;
     50   treap_update(p), treap_update(tmp);
     51   p = tmp;
     52 }
     53  
     54 void treap_insert(treap_node *&p, int rank) {
     55   if (p == null) {
     56     p = ++cnt_treap, Ls = Rs = null;
     57     Pri = rand(), Sz = 1, V = cnt;
     58     return;
     59   }
     60   ++Sz;
     61   if (Ls -> sz < rank) {
     62     treap_insert(Rs, rank - Ls -> sz - 1);
     63     if (Rs -> pri > Pri) treap_rotate(p, 1);
     64   } else {
     65     treap_insert(Ls, rank);
     66     if (Ls -> pri > Pri) treap_rotate(p, 0);
     67   }
     68 }
     69  
     70 void get_seq(treap_node *p) {
     71   if (p == null) return;
     72   get_seq(Ls);
     73   a[++cnt] = V;
     74   get_seq(Rs);
     75 }
     76 #undef Ls
     77 #undef Rs
     78 #undef Pri
     79 #undef Sz
     80 #undef Num
     81  
     82 int main() {
     83   int i, t;
     84   n = read();
     85   null = ++cnt_treap;
     86   null -> son[0] = null -> son[1] = null;
     87   null -> pri = null -> sz = null -> v = 0;
     88   root = null;
     89   for (cnt = 1; cnt <= n; ++cnt)
     90     treap_insert(root, read());
     91   cnt = 0;
     92   get_seq(root);
     93   memset(mn, 127, sizeof(mn));
     94   for (mn[0] = -inf, i = 1; i <= n; ++i) {
     95     t = upper_bound(mn, mn + len + 1, a[i]) - mn;
     96     if (mn[t - 1] <= a[i]) {
     97       mn[t] = min(mn[t], a[i]);
     98       ans[a[i]] = t;
     99       len = max(t, len);
    100     }
    101   }
    102   for (i = 1; i <= n; ++i)
    103     printf("%d
    ", ans[i] = max(ans[i], ans[i - 1]));
    104   return 0;
    105 }
    View Code

    方法二:倒过来做,从最后开始一个个删,用树状数组维护,求序列的前缀第k大

    BIT的这种应用方式也是蛮神的。。。

     1 /**************************************************************
     2     Problem: 3173
     3     User: rausen
     4     Language: C++
     5     Result: Accepted
     6     Time:248 ms
     7     Memory:3540 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <algorithm>
    13  
    14 #define lowbit(x) (x & -x)
    15 using namespace std;
    16 const int N = 100005;
    17 const int inf = 1e9;
    18 const int Maxlen = N * 8;
    19    
    20 int n, len;
    21 int a[N], ans[N], mn[N];
    22 int bit[N], b[N];
    23 char buf[Maxlen], *c = buf;
    24 int Len;
    25  
    26 inline int read() {
    27   int x = 0;
    28   while (*c < '0' || '9' < *c) ++c;
    29   while ('0' <= *c && *c <= '9')
    30     x = x * 10 + *c - '0', ++c;
    31   return x;
    32 }
    33  
    34 void print(int x) {
    35   if (x >= 10) print(x / 10);
    36   putchar(x % 10 + '0');
    37 }
    38  
    39 inline int get_kth(int k) {
    40   int res = 0, cnt = 0, i;
    41   for (i = 20; ~i; --i) {
    42     res += 1 << i;
    43     if (res >= n || cnt + bit[res] >= k) res -= 1 << i;
    44     else cnt += bit[res];
    45   }
    46   return res + 1;
    47 }
    48  
    49 inline void bit_del(int x) {
    50   while (x <= n)
    51     --bit[x], x += lowbit(x);
    52 }
    53  
    54 int main() {
    55   Len = fread(c, 1, Maxlen, stdin);
    56   buf[Len] = '';
    57   int i, t, w, mx;
    58   n = read();
    59   for (i = 1; i <= n; ++i) {
    60     b[i] = read(), ++bit[i];
    61     if (i + lowbit(i) <= n)
    62       bit[i + lowbit(i)] += bit[i];
    63   }
    64   for (i = n; i; --i) {
    65     a[w = get_kth(b[i] + 1)] = i;
    66     bit_del(w);
    67   }
    68   memset(mn, 127, sizeof(mn));
    69   for (mn[0] = -inf, i = 1; i <= n; ++i) {
    70     t = upper_bound(mn, mn + len + 1, a[i]) - mn;
    71     if (mn[t - 1] <= a[i]) {
    72       mn[t] = min(mn[t], a[i]);
    73       ans[a[i]] = t;
    74       len = max(t, len);
    75     }
    76   }
    77   for (i = 1, mx = 0; i <= n; ++i) {
    78     if (ans[i] > mx) mx = ans[i];
    79     print(mx);
    80     putchar('
    ');
    81   }
    82   return 0;
    83 }
    View Code

    (p.s. 在我的各种读入/输出/常数优化后,终于成为rank.1 yeah!)

    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    vue form dynamic validator All In one
    TypeScript api response interface All In One
    closable VS closeable All In One
    macOS 如何开启 WiFi 热点 All In One
    vue css inline style All In One
    vs2010里面 新建网站里面的 asp.net网站 和 新建项目里面的 asp.net Web应用程序 的区别 (下)
    牛腩新闻 59 整合添加新闻页 FreeTextBox 富文本编辑器,检测到有潜在危险的 Request.Form 值,DropDownList 的使用
    牛腩新闻 61尾声: error.aspx的使用 防止报错
    vs2010里面 新建网站里面的 asp.net网站 和 新建项目里面的 asp.net Web应用程序 的区别 (上)
    牛腩新闻 62:尾声续2 asp.net的编译和发布
  • 原文地址:https://www.cnblogs.com/rausen/p/4263402.html
Copyright © 2011-2022 走看看