[树状数组]jzoj4738. 神在夏至祭降下了神谕

本文介绍了一种使用动态规划解决区间划分问题的方法,并通过树状数组进行优化以提高效率。文章提供了完整的代码实现,展示了如何利用预处理数组判断区间内特定条件的满足情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Input 

Output 

Sample Input 

4 1
0 0 1 1

Sample Output

5

Data Constraint

Hint 

 Solution

很容易想到用dp,设f[i]为在i处划分的方案数,转移为f[i]+=f[j](j<i且j~i之间的人数差不超过k),时间O(n^{^{2}})。

考虑优化,我们用pre[x]表示1~x的夏之军人数减冬之军人数,对于f[i]可以转移的f[j]存在以下关系

pre[i]-pre[j]<=k

pre[i]-pre[j]>=-k

可得

pre[i]-k<=pre[j]<=pre[i]+k

那么就可以用树状数组维护这个区间的f[j]总和,时间O(nlogn)

code

代码敲级丑

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define N 100000+200
#define lowbit(x) x&(-x)
long long n,m;
long long f[N],tree[4*N],pre[N];
long long ti=200000;
long long mod=1000000007;
void add(long long x,long long ci)
{
	while(x<=300000)
	{
		tree[x]+=ci;
		x+=lowbit(x);
	}
}
long long query(long long x)
{
	long long cnt=0;
	while(x>0)
	{
		cnt+=tree[x];
		x-=lowbit(x);
	}
	return cnt;
}
int main()
{
	scanf("%lld %lld",&n,&m);
	for(long long i=1;i<=n;i++)
	{
		long long x;
		scanf("%lld",&x);
		if(x==1)
			pre[i]=pre[i-1]+1;
		else
			pre[i]=pre[i-1]-1;
	}
	for(long long i=1;i<=n;i++)
	{
		if(abs(pre[i])<=m)
			f[i]++;
		f[i]=(f[i]+query(pre[i]+m+ti)-query(pre[i]-m-1+ti))%mod;
		add(pre[i]+ti,f[i]);
	}
	printf("%lld",f[n]%mod);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值