1 条题解
-
1
#include<bits/stdc++.h> using namespace std; const int N=200009; int n; int a[N]; void input(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",&a[i]); } int as[N]; void compress(){ int j=1; for(int i=2;i<=n;++i) if(a[i]!=a[j]) a[++j]=a[i]; n=j; for(int i=1;i<=n;++i) as[i]=a[i]; sort(as+1,as+1+n); int nUnq=unique(as+1,as+1+n)-(as+1); for(int i=1;i<=n;++i) a[i]=lower_bound(as+1,as+1+nUnq,a[i])-as; } int f[5009][5009]; void solveDP(){ for(int i=1;i<=n;++i) for(int j=1;j<=n;++j)f[i][j]=0; for(int i=2;i<=n;++i) for(int j=1;j<=i-1;++j)if(a[j]!=a[i]){ f[i][j]=2; for(int k=1;k<=j-1;++k)if(a[k]!=a[i]&&a[k]!=a[j]) f[i][j]=max(f[i][j],f[j][k]+1); } int ans=1; for(int i=2;i<=n;++i) for(int j=1;j<=i-1;++j) ans=max(ans,f[i][j]); printf("%d\n",ans); } /* 压缩后:邻居都不同 离散化:数值变小 g[i][x]表示i号结尾的合法子序列最长长度 倒数第二位是pre[i][x]位置的元素 lastPos[v]表示数值v在当前访问的位置[1,2,..,i]内最后出现的位置 候选人容器中只考虑各个数值最后出现的位置,最多5个位置候选人 */ int g[N][10]; int pre[N][10]; int lastPos[N]; const int C=5; void solve(){ for(int i=1;i<=n;++i) for(int j=0;j<=C;++j)g[i][j]=0; for(int i=1;i<=n;++i)lastPos[i]=0; set<int> PRE; set<int>::iterator it; for(int i=1;i<=n;++i){ while(PRE.size()>5) PRE.erase(PRE.begin()); int cnti=0; for(it=PRE.begin();it!=PRE.end();++it) pre[i][++cnti]=*it; it=PRE.find(lastPos[a[i]]); if(it!=PRE.end()) PRE.erase(it); PRE.insert(i); lastPos[a[i]]=i; } for(int i=2;i<=n;++i) for(int pi=1;pi<=C;++pi){ int j=pre[i][pi]; if(!j)break; if(a[i]==a[j])continue; g[i][pi]=2; for(int pj=1;pj<=C;++pj){ int k=pre[j][pj]; if(!k)break; if(a[i]==a[k]||a[j]==a[k])continue; g[i][pi]=max(g[i][pi],g[j][pj]+1); } } int ans=1; for(int i=2;i<=n;++i) for(int pi=1;pi<=C;++pi){ int j=pre[i][pi]; if(!j)break; if(a[i]==a[j])continue; ans=max(ans,g[i][pi]); } printf("%d\n",ans); } int main(){ freopen("admission.in","r",stdin); freopen("admission.out","w",stdout); int t; cin>>t; int sN=0; while(t--){ input(); compress(); sN+=n; if(sN<=500) solveDP(); else solve(); } return 0; }
信息
- ID
- 6
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者