【洛谷 CF261D】Maxim and Increasing Subsequence【树状数组+DP】

题意翻译

题目
给你一个长度为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;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/108087249