Increasing Speed Limits HDU - 3030 dp 树状数组 离散化 上升子序列

Posted xuwanwei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Increasing Speed Limits HDU - 3030 dp 树状数组 离散化 上升子序列相关的知识,希望对你有一定的参考价值。

Increasing Speed Limite HDU 3030

题意

给你一个长度为m的数组A,你可以通过给的X,Y,Z计算获得一个长度为n的数组,问你这个n长的序列有多少个非空严格上升序列。

思路

dp

  • (dp[i]): 以第i个元素为结尾的非空严格上升序列个数
  • (dp[i] =sum_{j=1}^{i-1}{dp[j]}+1), 其中 (a[j]<a[i])
  • (ans = sum_{i=1}^n{dp[i]})
  • 用树状数组求前缀和

代码

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x));
typedef long long ll;
const int MAXN=500005;
const int MOD= 1000000007;
int n,m;
ll X,Y,Z;
int A[MAXN],a[MAXN],b[MAXN];
ll c[MAXN];
void update(int x,ll value){
	while(x<=n){
		c[x]=(c[x]+value)%MOD;
		x+=lowbit(x);
	}
}
ll getSum(int x){
	ll ret=0;
	while(x){
		ret=(ret+c[x])%MOD;
		x-=lowbit(x);
	}
	return ret;
}
int main(){
//	freopen("in.txt","r",stdin); 
	int T;
	scanf("%d",&T);
	for(int kase=1;kase<=T;kase++){
		scanf("%d%d%lld%lld%lld",&n,&m,&X,&Y,&Z);
		memset(c,0,sizeof(c));
		for(int i=0;i<m;i++)
			scanf("%d",&A[i]);
		for(int i=0;i<n;i++){
			a[i+1]=b[i+1]=A[i%m];
			A[i%m]=(X*A[i%m]+Y*(i+1))%Z;
		}
		sort(a+1,a+n+1);
		int an=unique(a+1,a+n+1)-a-1;
		int p;
		ll ans=0;
		ll tmp=0;
		for(int i=1;i<=n;i++){
			p=lower_bound(a+1,a+an+1,b[i])-a;
			tmp=getSum(p-1)+1;
			ans=(ans+tmp)%MOD;
			update(p,tmp);
		}
		printf("Case #%d: %lld
",kase,ans);
	}
        return 0;
} 

以上是关于Increasing Speed Limits HDU - 3030 dp 树状数组 离散化 上升子序列的主要内容,如果未能解决你的问题,请参考以下文章

C语言 "limits.h" 数据类型的界限值

LIMITS.H

bzoj4952[Wf2017]Need for Speed 二分

C 标准库系列之limits.h

在 Alpine Linux 上安装 Pillow 时没有这样的文件或目录“limits.h”

包含 <limits.h> 后未定义 HOST_NAME_MAX