CF261D Maxim and Increasing Subsequence
题目大意
给你一个长度为n的B数组,A表示B数组复制ttt遍后首尾相连后的数组,求A的最长上升子序列 有k组询问 maxb表示B数组中最大的数
题目分析
观察样例与数据可以知道,当t>=sum时,答案就是sum,其中sum为序列中不同数字的个数,因为是严格单调的。
sum一定小于maxb。
dp,找最大值用树状数组
AC代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int k,n,maxb,t,s,sum,a[100005],b[100005],f[100005],tree[100005];
int lowbit(int x){
return x&(-x);}
int find(int x)//查询
{
int s=0;
for(;x;x-=lowbit(x))
s=max(tree[x],s);
return s;
}
void gg(int x,int y)//更改
{
for(;x<=maxb;x+=lowbit(x))
tree[x]=max(tree[x],y);
}
int main()
{
cin>>k>>n>>maxb>>t;
while(k--)
{
s=sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(b[a[i]]!=k+1)sum++;
b[a[i]]=k+1;
}
if(t>=sum)
{
cout<<sum<<endl;
continue;
}
memset(tree,0,sizeof(tree));//初值
memset(f,0,sizeof(f));
for(int i=1;i<=t;i++)//周期
for(int j=1;j<=n;j++)//位置
{
int c=find(a[j]-1)+1;
if(c>f[j])//判断能不能修改树状数组,f[j]记录上一周期
{
f[j]=c;
s=max(s,c);
gg(a[j],c);
}
if(s>sum)break;//答案不可能超过sum
}
printf("%d\n",s);
}
}