1. 程式人生 > 其它 >程式碼源每日一題 最長有趣子序列

程式碼源每日一題 最長有趣子序列

最長有趣子序列

題目描述

定義一個序列是有趣的當且僅當他相鄰兩項的與不為0

即對一個長為\(n\)的序列\(\{a\}\), 滿足\(\forall x< n\ a[x]\&a[x+1] \neq 0\)

現在給你一個長為\(n\)的序列\(\{a\}\), 請問最長的有趣子序列的長度是多少

輸入描述

一行一個整數\(1\leq n \leq 10^6\)

接下來一行\(n\)個整數\(1 \leq a_i \leq 2^{31} - 1\)

輸出描述

一行一個整數, 用於描述最長有趣子序列的長度

樣例輸入

3
1 2 3

樣例輸出

2

題目分析

可以這樣考慮,\(table\)是這樣的一種陣列:

i=1,table=1b
i=2,table=10b
i=3,table=100b
i=4,table=1000b
i=4,table=10000b
......(以上都是二進位制)

也就是說,\(table[i]=1<<i\)

設計一個ans陣列,表示\(\&table[i]!=0\)的數量的最大值,也就是對於每一位二進位制做\(dp\)

\[ans[i]=\max_1^{40}(table[i]) \\table=max(ans,table) \]

AC code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+7;
ll table[40],a[N];
int ans[40];
int main() {
	int n;
	scanf("%d",&n);
	for(int i = 1 ; i <= n ; i++ ) {
		scanf("%d",&a[i]);
	}
	for(int i = 0 ; i < 40 ; i++)
		table[i] = 1ll<<i;
	for(int i = 1 ; i <= n ; i++) {
		int t = 0;
		for(int j = 0 ; j < 32 ; j++)
			if(a[i]&table[j])
				t = max(t,++ans[j]);
		for(int j = 0 ; j < 32 ; j++)
			if(a[i]&table[j])
				ans[j] = t;
	}
	int res = 0;
	for(int i = 0 ; i < 32 ; i++)
		res = max(ans[i],res);
	cout << res;
}