1921: 晴天的序列
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 216 Solved: 17
Submit Status Web Board
Description
给定一个长度为n的数字序列a,从中选取一个长为m的子序列b满足 b[i]&b[i-1]!=0 (2<=i<=m)
求最大的m。
Input
第一行输入一个整数t,代表有t组测试数据。
每组数据第一行输入一个整数n代表a序列的长度,接下来一行输入n个正整数表示ai(0<i<=n)。
1<=t<=20,0<=n<=100000,0<=ai<=1e9。
Output
一个整数表示最大的m。
Sample Input
1
3
1 1 1
Sample Output
3
HINT
Source
继续编题目名。
记录每一位的上一个是1的数的地方,然后dp[i] = max(dp[i] , dp[x]) 这个x用栈或者vector记录就行了。
代码如下:
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <stack>
#include <algorithm>
using namespace std;
#define CLR(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
#define MAX 100000
int dp[MAX+11];
stack<int> s[MAX+11]; //第i位为1的数
int main()
{
int u;
int n;
int t;
int ans;
scanf ("%d",&u);
while (u--)
{
scanf ("%d",&n);
for (int i = 1 ; i <= n ; i++)
{
while (!s[i].empty())
s[i].pop();
}
ans = 0;
for (int i = 1 ; i <= n ; i++)
{
dp[i] = 1;
scanf ("%d",&t);
while (t)
{
int pos = log2(t & (-t)) + 1;
t -= t & (-t);
if (s[pos].empty())
s[pos].push(i);
else
{
dp[i] = max (dp[i] , dp[s[pos].top()] + 1);
s[pos].push(i);
}
}
ans = max (ans , dp[i]);
}
printf ("%d\n",ans);
}
return 0;
}