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

题意翻译
给你一个长度为 n n n B B B数组, A A A表示 B B B数组复制 t t t遍后首尾相连后的数组,求 A A A的最长上升子序列 有 k k k组询问 m a x b maxb maxb表示 B B B数组中最大的数.
原题链接.


解题思路
首先我们可以得到:当 t t t大于等于当前数列不同数字的个数时,答案就是不同数字的个数。

  • 证明:
    假设当前不同数字的个数为 3 3 3, 即 s u m = 3 sum=3 sum=3;
    此时共有 t t t 个相同的序列,
    那么我们在第 t t t 个序列选择第 t 小的数 ( t < = s u m ) (t<=sum) t<=sum
    此时一定能保证生成含有 s u m sum sum 个元素的最长上升子序列。

图示:在这里插入图片描述
接下来处理上述不成立的情况:
我们可以设一个 f [ i ] f[i] f[i] 表示当前周期的最长序列长度,由于数据太大,所以要开滚动数组。
当枚举到当前周期时,我们考虑怎样转移。
最长上升子序列的动态转移方程为
f [ i ] = m a x ( f [ j ] ) + 1 ( j < i , a [ j ] < a [ i ] ) 。 f [ i ] = m a x ( f [ j ] ) + 1 ( j < i , a [ j ] < a [ i ] ) f[i]=max(f[j])+1(j<i,a[j]<a[i])。f[i]=max(f[j])+1(j<i,a[j]<a[i]) f[i]=max(f[j])+1(j<i,a[j]<a[i])f[i]=max(f[j])+1(j<i,a[j]<a[i])
其实这道题也是一样的,我们找到比 a [ j ] a[j] a[j] 小的数,也就是 a [ j ] − 1 a[j]−1 a[j]1
我们就可以想到用树状数组维护,显然,我们用树状数组维护的是最大值。


代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,k,maxb,t,ans,sum,a[100010],tree[100010],b[100010],f[100010];
void find(int x,int y){
	for(int i=x;i<=maxb;i+=i&(-i))
		tree[i]=max(tree[i],y);//求区间最大值
}
int query(int x){
	int bsy=0;
	for(int i=x;i;i-=i&(-i))
		bsy=max(bsy,tree[i]);//修改区间最大值
	return bsy;
}
int main(){
	scanf("%d%d%d%d",&k,&n,&maxb,&t);
	while(k--){
		int sum=0,ans=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			if(b[a[i]]!=k+1)
				sum++;
			b[a[i]]=k+1;//标记求sum,不用赋初值,因为每次k+1都不一样		
		}	
		if(t>=sum)//特判
		{
			printf("%d\n",sum);
			continue;
		}
		memset(f,0,sizeof(f));
		memset(tree,0,sizeof(tree));
		for(int i=1;i<=t;i++)
		{
			for(int j=1;j<=n;j++)
			{
				int c=query(a[j]-1)+1;
				if(c>f[j])
				{
					f[j]=c;
					ans=max(ans,f[j]);
					find(a[j],c);
				}
				if(ans>sum)//不能存在ans>sum的情况
					break;
			}
		}
		printf("%d\n",ans); 
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值