1. 程式人生 > >18.10.9 不好做的最長上升子序列(nlogn樹狀數組解LIS)

18.10.9 不好做的最長上升子序列(nlogn樹狀數組解LIS)

algo eve void operator ++ 做的 pre fin pro

描述

一個數的序列bi,當b1 < b2 < ... < bS的時候,我們稱這個序列是上升的。對於給定的一個序列(a1, a2, ..., aN),我們可以得到一些上升的子序列(ai1, ai2, ..., aiK),這裏1 <= i1 < i2 < ... < iK <= N。比如,對於序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。這些子序列中最長的長度是4,比如子序列(1, 3, 5, 8).

你的任務,就是對於給定的序列,求出最長上升子序列的長度。

輸入

輸入的第一行是序列的長度N (1 <= N <= 300000)。第二行給出序列中的N個整數,這些整數的取值範圍都在0到100000000之間。輸出最長上升子序列的長度。

樣例輸入

7
1 7 3 5 9 4 8

樣例輸出

4
技術分享圖片
 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10
#include <vector> 11 12 #define lowbit(x) x&(-x) 13 14 using namespace std; 15 16 struct node { 17 int pos,value; 18 bool operator<(node a) { 19 if (value == a.value) 20 return pos > a.pos; 21 return value < a.value; 22 } 23 };
24 25 const int maxn = 300005; 26 node n[maxn]; 27 int N,c[maxn]; 28 29 int query(int pos) { 30 int res = 0; 31 while (pos > 0) { 32 res = max(c[pos], res); 33 pos -= lowbit(pos); 34 } 35 return res; 36 } 37 38 void change(int pos,int len) { 39 while (pos <= N) { 40 c[pos] = max(c[pos], len); 41 pos += lowbit(pos); 42 } 43 } 44 45 int getmax() { 46 int s = N,res=0; 47 while (s > 0) { 48 res = max(res, c[s]); 49 s -= lowbit(s); 50 } 51 return res; 52 } 53 54 void process() { 55 for (int i = 1; i <= N; i++) { 56 int lis; 57 lis = query(n[i].pos) + 1; 58 change(n[i].pos, lis); 59 } 60 printf("%d\n", getmax()); 61 } 62 63 64 int main() 65 { 66 scanf("%d", &N); 67 for (int i = 1; i <= N; i++) { 68 int val; 69 scanf("%d", &val); 70 n[i].pos = i, n[i].value = val; 71 } 72 sort(n + 1, n+N+1); 73 process(); 74 return 0; 75 }
View Code

我很好奇他們是怎麽發現數據的範圍一開始是錯的??

課上睡著了沒聽到這題,看了PPT做的

18.10.9 不好做的最長上升子序列(nlogn樹狀數組解LIS)