琪露诺闲来无事,用冰块制造了了N个台阶,沿直线依次摆放,编号1, 2, 3...,⑨, ...N,分别高H(1), H(2), ... H(N)
琪露诺很满意自己的作品,想把自己抓到的青蛙放到台阶上玩,玩法也很简单。 青蛙最开始在第一个台阶上,它只能往前面编号更大的台阶上跳。如果现在在第k个台阶上,它至少要跳到第(k+L)个台阶上,最多只能跳到第(k+R)个台阶上,而且目标台阶现在所在的这个台阶,它们高度的绝对值之差,不能超过T。否则青蛙会跳不上去或者摔死。(这时候只有琪露诺给它续它才能复活,而琪露诺是不会给青蛙续的)。
琪露诺想知道青蛙跳到第N个,也就是最后一个台阶上,有多少种路线呢?琪露诺是天才魔法少女,但是数数用的是⑨进制,她数出来的结果别人是无法理解的,所以她找你来帮忙了,请你告诉大家,青蛙有有多少条路线可以走呢?告诉大家方案数对998244353取模的结果就可以啦,无法到达的话,方案数自然就是0。
第一行4个正整数,N, L, R, T,含义如题面所示
接下来第二行,N个正整数,依次表示这N个高台的高度。
青蛙跳到最后一个高台上面的方案数对998244353取模的结果。
3 2 2 0
1 100 1
1
只有一种方案,从第1个高台直接跳到第3个高台。第二个高台虽然高100但是并不会影响青蛙跳过它,因为这些青蛙是经过早苗开光的
5 1 2 5
1 2 3 4 5
5
#5条路线分别是(数字代表高台的编号):
1-2-3-4-5
1-2-3-5
1-2-4-5
1-3-4-5
1-3-5
20 1 4 12
1 2 3 4 5 6 7 100 9 10 11 12 11 100 1 2 3 4 5 6
27680
良心大♂样例
对于20%的数据:N <= 20,
对于另外20%的数据:N <= 10000, R-L+1 <= 1000
对于另外20%的数据:N <= 20000,T = 0
对于另外20%的数据:N <= 20000。
对于100%的数据:N <= 100000, 1 <= R-L+1 <= N,1 <= H(i) <= 10000, T <= 10000
by sxysxy。原题地址: http://syzoj.com/problem/314
题解:
计数题 但状态转移时间复杂度太高 就必须要用一种数据结构来维护
方程:f[i]=sigma(j,max(1,i-R) to i-L)且abs(H[i]-H[j]<=T)f[j](i>L)
很容易看出 一维数据结构依然满足不了高效 可以采用二维数据结构
我们维护n棵线段树,每棵线段树下标为高度,对于第i棵线段树,维护第1-i个冰块的方案数之和,那么f[i]变为在第i-L棵线段树与第max(1,i-R)棵线段树的差线段树上查询[H[i]-T,H[i]+T]这个区间权值和
n棵线段树空间会爆,要用可持久化来减少空间损失。
代码:
#include#include #include #include using namespace std; const int maxn=100000+10; const long long MOD=998244353; long long f[maxn]={0}; int root[maxn*50],ls[maxn*50],rs[maxn*50]; long long summ[maxn*50]; int sz=0; int h[maxn]; int n,m; inline void insert(int last,int l,int r,int &rt,int x,long long v){ rt=++sz; summ[rt]=((summ[last]+v)%MOD+MOD)%MOD; if(l==r) return ; int mid=(l+r)>>1; ls[rt]=ls[last],rs[rt]=rs[last]; if(mid>=x) insert(ls[last],l,mid,ls[rt],x,v); else insert(rs[last],mid+1,r,rs[rt],x,v); } inline long long query(int L,int R,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return summ[R]-summ[L]; if(l==r) return 0; int mid=(l+r)>>1; long long ans=0; if(mid>=ql) ans+=query(ls[L],ls[R],l,mid,ql,qr); ans%=MOD; if(mid =1){ long long T=query(root[l-1],root[r],1,10000,max(h[i]-m,1),min(h[i]+m,10000))%MOD; f[i]=(T%MOD+MOD)%MOD; } insert(root[i-1],1,10000,root[i],h[i],f[i]); } printf("%lld\n",f[n]); return 0; }