For a set of sequences of integers{a1,a2,a3,...an}, we define a sequence{ai1,ai2,ai3...aik}in which 1<=i1<i2<i3<...<ik<=n, as the sub-sequence of {a1,a2,a3,...an}. It is quite obvious that a sequence with the length n has 2^n sub-sequences. And for a sub-sequence{ai1,ai2,ai3...aik},if it matches the following qualities: k >= 2, and the neighboring 2 elements have the difference not larger than d, it will be defined as a Perfect Sub-sequence. Now given an integer sequence, calculate the number of its perfect sub-sequence.
长度为n的整数序列,它有2n个子序列。如果子序列满足长度≥2, 而且任意相邻的两个整数的差的绝对值不大于d,称为完美子序 列。
求一个整数序列完美子序列的个数,结果对9901取模。
一道 DP 题,在 DP 的基础上用线段树优化,但是 OJ 上一直都评测出运行错误,不知道为什么,发过来找大佬求助一下
#include<bits/stdc++.h>
#define MAXN 100010
#define MOD (ll)9901
using namespace std;
typedef long long ll;
struct node{
/*
l,r -> 区间
val -> 区间和
*/
ll l,r;
ll val;
};
ll n,d,ans,len;
/*
num 是原数据,tmp 用来离散化,里面存了 num[i], num[i]+d, num[i]-d
*/
ll tmp[MAXN*3],num[MAXN];
node tree[MAXN<<2];
void push_up(ll now){
tree[now].val=tree[now*2].val+tree[now*2+1].val;
}
void build(ll now,ll l,ll r){
tree[now].l=l; tree[now].r=r;
if(tree[now].l==tree[now].r){
tree[now].val=0;
return ;
}
ll mid=(l+r)>>1;
build(now*2,l,mid);
build(now*2+1,mid+1,r);
push_up(now);
}
/*
updata(now,i,x) -> 在第 i 个位置上加上 x
*/
void updata(ll now,ll i,ll x){
if(tree[now].l==tree[now].r){
tree[now].val+=x; tree[now].val%=MOD;
return ;
}
ll mid=(tree[now].l+tree[now].r)>>1;
if(i<=mid) updata(now*2,i,x);
else updata(now*2+1,i,x);
push_up(now);
}
ll query(ll now,ll l,ll r){
if(tree[now].l>=l&&tree[now].r<=r){
return tree[now].val%MOD;
}
ll mid=(tree[now].l+tree[now].r)>>1;
if(r<=mid) return query(now*2,l,r)%MOD;
else if(l>mid) return query(now*2+1,l,r)%MOD;
else return (query(now*2,l,mid)%MOD+query(now*2+1,mid+1,r)%MOD)%MOD;
}
int main(){
while(~scanf("%lld%lld",&n,&d)){
for(ll i=1;i<=n;i++){
scanf("%lld",&num[i]);
tmp[++len]=num[i];
tmp[++len]=num[i]-d;
tmp[++len]=num[i]+d;
}
sort(tmp+1,tmp+len+1);
len=unique(tmp+1,tmp+len+1)-tmp-1;
build(1,1,len); ans=0;
for(ll i=1;i<=n;i++){
ll now=num[i];
ll val1=now-d,val2=now+d;
//查找 num[i], num[i]-d, num[i]+d 离散化后对应的下标
ll pos1=lower_bound(tmp+1,tmp+len+1,val1)-tmp;
ll pos2=lower_bound(tmp+1,tmp+len+1,val2)-tmp;
ll pos3=lower_bound(tmp+1,tmp+len+1,now)-tmp;
ll sum=query(1,pos1,pos2);
ans+=sum; ans%=MOD;
updata(1,pos3,sum+1);
}
printf("%lld\n",ans);
}
return 0;
}