牛客练习赛56-C

C 小魂和他的数列牛客练习赛56-C_第1张图片

预处理出该序列中的每个数是第几大的,然后依次按照大小插入到树状数组中,
没插入一个数字,就判断现在在数组中的数比当前数小的数有多少个,让后逐层更新一下,更新k层,最后把低K层的数加起来即可。

#include
#include
using namespace std;
typedef long long ll;
const int N=600500;
const ll mod=998244353;
ll c[N][15],ans[N][15];
int a[N],b[N];
int n,k;
void add(int i,int x,int y) {
	for(; x<=n; x+=x&-x)
		c[x][i]=(c[x][i]+y)%mod;
}
ll ask(int i,int x) {
	ll ans=0;
	for(; x; x-=x&-x)ans=(ans+c[x][i])%mod;
	return ans;
}
int main() {
	scanf("%d %d",&n,&k);
	for(int i=1; i<=n; ++i) {
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	sort(b+1,b+n+1);
	int len=unique(b+1,b+n+1)-b-1;
	for(int i=1; i<=n; ++i) {
		a[i]=lower_bound(b+1,b+len+1,a[i])-b;
	}
	ll anss=0;
	for(int i=1; i<=n; ++i) {
		add(1,a[i],1);
		for(int j=2; j<=min(i,k); ++j) {
			ans[i][j]=ask(j-1,a[i]-1);
			add(j,a[i],ans[i][j]);
		}
		anss=(anss+ans[i][k])%mod;
	}
	printf("%lld\n",anss);
	return 0;
}

好狠一道题,活生生改了我一上午,同样的代码,同时交好几发,三分之一过,三分之二超时,最后把二维数组的的两个维度换一下,快了将近一半时间,不知道是玄学还是有什么依据,太菜了啊。

你可能感兴趣的:(数据结构,DP)