神在夏至祭降下了神谕 题解

  先说一句题外话,有谁看到的第一眼看成了某站的知名up主夏日祭?

题面

夏至祭是一场迎接祖灵于夏季归来同时祈求丰收的庆典。村里的男人会在广
场上演出冬之军跟夏之军的战争,夏之军会打倒冬之军的大将冬男,再放火将他
连山车一起烧掉。
谢尔吉斯村长已经选好了N个人参加演出,其中一些人负责演夏之军,另一
些人负责演冬之军。由于人数众多,谢尔吉斯想把这N个人分成若干个连续的
段。为了保证演出的顺利进行,每段的夏之军人数与冬之军人数之差的绝对值不
能超过K。
谢尔吉斯想知道符合条件的划分方案有多少种。由于符合条件的方案有很多,
你只要输出方案数除以1e9+7的余数。
【输入格式】
第一行两个整数N,K,意义如题目描述所示。 接下来一行N个整数,第i个整数为0表示第i个人是夏之军,1表示第i个
人是冬之军。
【输出格式】
一行一个整数,表示符合条件的方案数除以1e9+7的余数。
【样例输入】
4 1
0 0 1 1
【样例输出】
5
【样例说明】
合法的5种方案分别为:
0 0 1 1
0 0 1|1
0|0 1 1
0|0 1|1
0|0|1|1
而00|1|1不是合法的方案, 因为第一段“00”中夏之军人数为2,冬之军人数为0,人数之差的绝对值超过了K。
【数据范围】
20%的数据保证,N≤20。
50%的数据保证,N≤8000。
另有15%的数据保证,所有的人都是夏之军。
另有15%的数据保证,K=0。
100%的数据保证,1≤N≤10^5,0≤K≤N。
 
 
 
 
 
 
 
比较明显的,这是一道dp;
f[i]+=f[j] (i~j符合题中所说的要求);
用s[i]表示原数组的前缀和,那么符合的条件就是:abs(2*s[i]-i+2*s[j-1]-(j-1))<=k
那么设w[i]=2*s[i]-i;
显然,w[i]-k<=w[j]<=w[i]+k
发现了什么?转移的位置是一个连续区间;
这时候我们就可以使用Splay或树状数组或线段树来大力维护dp状态;
然后就可以AC掉了;
注意w[i]-k有可能是负数,所以要将数组扩大几倍防止下标出现负数;

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define p 1000000007
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
int a[100010],sum[100010];
long long f[100010];
long long ss[100010];
int n,k;
long long w[100010];
long long c[600010];
class node{
	public:
	inline int lowbit(register int x){
		return x&(-x);
	}
	void add(register int x,register long long v){
		while(x<=6*n){
			c[x]=(c[x]+v)%p;
			x+=lowbit(x);
		}
	}
	int query(register int x){
		register long long res=0;
		while(x>0){
			res=(res+c[x])%p;
			x-=lowbit(x);
		}
		return res%p;
	}
}tree;
template<class nT>
inline void read(nT& x)
{
	char c;while(c=getchar(),!isdigit(c));
	x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
}
int main()
{
	read(n); read(k);
	inc(i,1,n){
		read(a[i]); sum[i]=(sum[i-1]+a[i]);	
		w[i]=2*sum[i]-i;
	}
	f[0]=1;
	tree.add(w[0]+2*n,1);
	inc(i,1,n){
		long long tmp1=tree.query(w[i]+k+2*n),tmp2=tree.query(w[i]-k-1+2*n);
		long long tmp=((tmp1-tmp2)%p+p)%p;
		f[i]=tmp%p;
		tree.add(w[i]+2*n,f[i]);
	}
	cout<<f[n]%p;
}
/*
2 1
1 0

3 0
0 1 0

30 7
1 0 0 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 1

49 17
0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 1 1 0 1 1 0 1
*/

 

posted @ 2019-11-04 20:16  神之右大臣  阅读(209)  评论(0编辑  收藏  举报