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

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

我不会用树状数组求这个原排列,于是我只好用线段树。。。毕竟 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 >> 1;
 24     Build(ls(x), l, mid);
 25     Build(rs(x), mid + 1, 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 = 0;
 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 >> 1;
 53     if (t <= mid) Modify(ls(x), l, mid, s, t, d);
 54         else if (s > mid) Modify(rs(x), mid + 1, r, s, t, d);
 55         else Modify(ls(x), l, mid, s, mid, d), Modify(rs(x), mid + 1, r, mid + 1, 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 >> 1;
 63     if (h[rs(x)].Min <= h[ls(x)].Min)
 64         return Query(rs(x), mid + 1, 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 = 1; i <= n; i ++)
 77         scanf("%d", Pos + i);
 78     Build(1, 1, n);
 79     for (int i = 1; i <= n; i ++)
 80     {
 81         int t = Query(1, 1, n);
 82         Modify(1, 1, n, 1, t, 1);
 83         Modify(1, 1, n, t, t, n);
 84         if (!T[0] || T[T[0]] < t)
 85         {
 86             T[++ T[0]] = t;
 87             F[t] = T[0];
 88         }
 89         else
 90         {
 91             int x = lower_bound(T + 1, T + T[0] + 1, t) - T;
 92             T[x] = t;
 93             F[t] = x;
 94         }
 95     }
 96     for (int i = 1, Max = 0; 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 0;
107 }
3173_Gromah

 

posted @ 2015-06-25 21:44  Gromah  阅读(236)  评论(0编辑  收藏  举报