BZOJ4300 绝世好题
Description
给定一个长度为\(n\)的数列\(a_{i}\),求\(a_{i}\)的子序列\(b_{i}\)的最长长度,满足\(b_{i} \& b_{i-1} \neq 0(2 \le i \le len)\)。
Input
输入文件共\(2\)行。
第一行包括一个整数\(n\)。
第二行包括\(n\)个整数,第\(i\)个整数表示\(a_{i}\)。
Output
输出文件共一行。
包括一个整数,表示子序列\(b_{i}\)的最长长度。
Sample Input
3
1 2 3
Sample Output
2
HINT
\(n \le 100000,ai \le 2 \times 10^{9}\)
好吧,这题我是骗掉的。\(f_{i}\)表示以\(a_{i}\)结尾的最长子序列,将序列按\(f\)插入平衡树中。之后从枚举\(a_{i}\),每次从树中从大到小取出\(f_{j}\),若合法便把\(a_{i}\)接到\(a_{j}\)后,break。将\(f_{i}\)更新,插入平衡树。
#include<cstdio>
#include<cstdlib>
#include<set>
using namespace std;
#define maxn (100010)
int N,ans,f[maxn],A[maxn];
struct cmp { inline bool operator ()(int a,int b) { return f[a] != f[b]?(f[a]>f[b]):(a>b); } };
set <int,cmp> S;
inline int gi()
{
char ch; int ret = 0,f = 1;
do ch = getchar(); while (!(ch >= '0'&&ch <= '9')&&ch != '-');
if (ch == '-') f = -1,ch = getchar();
do ret = ret*10+ch-'0',ch = getchar(); while (ch >= '0'&&ch <= '9');
return ret*f;
}
int main()
{
freopen("4300.in","r",stdin);
freopen("4300.out","w",stdout);
N = gi();
for (int i = 1;i <= N;++i) A[i] = gi();
for (int i = 1;i <= N;++i)
{
set <int,cmp> :: iterator it,ed;
f[i] = 1;
for (it = S.begin(),ed = S.end();it != ed;++it)
if (A[i]&A[*it]) { f[i] = f[*it]+1; break; }
S.insert(i);
}
for (int i = 1;i <= N;++i) if (f[i] > ans) ans = f[i];
printf("%d",ans);
fclose(stdin); fclose(stdout);
return 0;
}
高考结束,重新回归。