CF261D Maxim and Increasing Subsequence(树状数组)

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);
    }
}

谢谢

猜你喜欢

转载自blog.csdn.net/weixin_45524309/article/details/108091962