题意:
好麻烦不想解释,来个连接:传送门
思路:
首先可以想到一个n方的dp:
另f[i]为从开始到第i个中最长的子序列长度
则显然有状态转移方程:f[i]=max(f[i],f[j]+1);(类似最长不下降子序列)
那么怎么简化呢?注意到a一定小于200,
也就是说当i和j相差过大的时候,a[i]a[j]多大是不起作用的,因为只能影响到后8位,也就是说事实上j只需要往前走400位就可以。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int inf=1e9+9;
const ll INF=1e18l;
/*
priority_queue<int> big_heep;
priority_queue<int,vector<int>,greater<int> > small_heep;
struct cmp{//if return true,it means that the number in the left was smaller than the right one
bool operator () (int a,int b){
}
};
*/
int a[400005];
int f[400005];
void work(){
int n;
cin>>n;
for (int i=0;i<n;i++) cin>>a[i],f[i]=1;
for (int i=0;i<n;i++){
for (int j=i-1;j>=0 && (i - j) <= 400;j--){
if ((i^a[j])<(j^a[i]))
f[i]=max(f[i],f[j]+1);
}
}
int maxn=0;
for (int i=1;i<=n;i++) maxn=max(f[i],maxn);
cout<<maxn<<"\n";
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t;
cin>>t;
while (t--){
work();
}
return 0;
}