题意翻译
题目
给你一个长度为n的B数组,A表示B数组复制t遍后首尾相连后的数组,求A的最长上升子序列 有k组询问 maxb表示B数组中最大的数
输入输出样例
输入 #1
3 3 5 2
3 2 1
1 2 3
2 3 1
输出 #1
2
3
3
分析:
因为是严格单调的 所以当 t > = t>= t>=序列中不同数字个数 Q Q Q时 A n s Ans Ans就是 Q Q Q
然后就可以 D P DP DP了 用树状数组找最大值 最终 A n s Ans Ans是不会超过 Q Q Q的
可借此优化 就不会 T L E TLE TLE了 … … …… ……线段树会 T L E … … TLE…… TLE……
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100100;
int k,n,maxn,t,sum;
int a[N],v[200*N];
int f[N],tree[N];
int lowbit(int x){
return x&(-x);}
void update(int x,int y)
{
for(;x<=maxn;x+=lowbit(x)) //改权
tree[x]=max(tree[x], y);
}
int find(int x)
{
int ans=0;
for(;x;x-=lowbit(x))
ans=max(ans,tree[x]); //求最大值
return ans;
}
int main(){
scanf("%d%d%d%d",&k,&n,&maxn,&t);
while(k--)
{
sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(v[a[i]]!=k+1)
sum++; //统计不同数字个数
v[a[i]]=k+1;
}
if(t>=sum) //严格单调
{
printf("%d\n",sum);
continue;
}
int ans=0;
for(int i=1;i<=N;i++)
f[i]=tree[i]=0; //清空数组
for(int i=1;i<=t;i++) //周期
for(int j=1;j<=n;j++) //位置
{
int x=find(a[j]-1)+1;
if(x>f[j]) //能否修改树状数组
{
f[j]=x;
ans=max(ans,x); //最大值
update(a[j],x);
}
if(ans>=sum) break; //优化
}
printf("%d\n",ans);
}
return 0;
}