您的位置:首页 > 其它

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

2015-06-25 21:44 381 查看

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

我不会用树状数组求这个原排列,于是我只好用线段树。。。毕竟 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
, A
, T
, F
;
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

 

转载于:https://www.cnblogs.com/gromah/p/4601012.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: