POJ 3903 Stock Exchange :
此題也是簡單的最長上升子序列問題,但由於數列長度n較大(n <= 100000),所以普通的O(n^2)是會超時的,所以要用O(nlogn)算法。加輸入輸出優化後直接進status前三名,哈哈
代碼如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std ;
const int MAXN = 1e5 + 5 ;
int s[MAXN] ;
int dp[MAXN] ;
int n ;
int stap[MAXN] ;
int top ;
inline void RD(int &a)
{
a = 0 ;
char t ;
do
{
t = getchar() ;
}while ( t < '0' || t > '9') ;
a = t - '0' ;
while ((t = getchar()) >= '0' && t <= '9')
{
a = a * 10 + t - '0' ;
}
}
inline void OT(int a)
{
if(a >= 10)
{
OT(a / 10) ;
}
putchar(a % 10 + '0') ;
}
void init()
{
int i , j ;
for(i = 1 ; i <= n ; i ++)
{
//scanf("%d" , &s[i]) ;
RD(s[i]) ;
}
}
void solve() // O(n^2) 算法
{
int i , j ;
dp[1] = 1 ;
for(i = 2 ; i <= n ; i ++)
{
dp[i] = 1 ;
for(j = 1 ; j < i ; j ++)
{
if(s[i] > s[j] && dp[i] < dp[j] + 1)
{
dp[i] = dp[j] + 1 ;
}
}
}
int MAX = -1 ;
for(i = 1 ; i <= n ; i ++)
{
if(MAX < dp[i])
MAX = dp[i] ;
}
printf("%d\n" , MAX) ;
}
void solve2() // O(n log n) 算法
{
top = 0 ;
stap[++ top] = s[1] ;
int i ;
for(i = 2 ; i <= n ; i ++)
{
if(s[i] > stap[top])
{
stap[++ top] = s[i] ;
}
else if(s[i] < stap[top])
{
int left , right , mid ;
left = 1 ;
right = top ;
while (left < right)
{
mid = (left + right) / 2 ;
if(stap[mid] < s[i])
{
left = mid + 1 ;
}
else if(stap[mid] == s[i])
{
break ;
}
else
{
right = mid ; // 注意不是 mid - 1 !!
}
}
mid = (left + right) / 2 ;
stap[mid] = s[i] ;
}
}
OT(top) ;
puts("") ;
}
int main()
{
while (scanf("%d" , &n) != EOF)
{
init() ;
//solve() ;
solve2() ;
}
return 0 ;
}
POJ 1631 Bridging signals:
方法同上,只不過輸入發生了點變化。
代碼如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std ;
const int MAXN = 1e5 + 5 ;
int s[MAXN] ;
int dp[MAXN] ;
int n ;
int stap[MAXN] ;
int top ;
inline void RD(int &a)
{
a = 0 ;
char t ;
do
{
t = getchar() ;
}while ( t < '0' || t > '9') ;
a = t - '0' ;
while ((t = getchar()) >= '0' && t <= '9')
{
a = a * 10 + t - '0' ;
}
}
inline void OT(int a)
{
if(a >= 10)
{
OT(a / 10) ;
}
putchar(a % 10 + '0') ;
}
void init()
{
RD(n) ;
int i , j ;
for(i = 1 ; i <= n ; i ++)
{
RD(s[i]) ;
}
}
void solve2() // O(n log n) 算法
{
top = 0 ;
stap[++ top] = s[1] ;
int i ;
for(i = 2 ; i <= n ; i ++)
{
if(s[i] > stap[top])
{
stap[++ top] = s[i] ;
}
else if(s[i] < stap[top])
{
int left , right , mid ;
left = 1 ;
right = top ;
while (left < right)
{
mid = (left + right) / 2 ;
if(stap[mid] < s[i])
{
left = mid + 1 ;
}
else if(stap[mid] == s[i])
{
break ;
}
else
{
right = mid ; // 注意不是 mid - 1 !!
}
}
mid = (left + right) / 2 ;
stap[mid] = s[i] ;
}
}
OT(top) ;
puts("") ;
}
int main()
{
int T ;
scanf("%d" , &T) ;
while (T --)
{
init() ;
solve2() ;
}
return 0 ;
}