题目大意
给一串子序列(int)和一个数d,求完美子序列数(按原数列中顺序排列)。
完美子序列:任意相邻两数之间的差不大于d。长度大于等于2。
思路
树状数组优化dp:
dp[i] = sum(dp[j]), i - d <= j <= i + d;
dp[i]++; (dp中应包括自身长度为1的子序列,但不加到答案上)
数列范围为整形(包括负),范围过大应用树状数组应该离散化。STL: unique(), lower_bound()
HINT
答案取模,程序中注意谨慎地处处取模,以及(a + mod) % mod,防止出现负数。
给一串子序列(int)和一个数d,求完美子序列数(按原数列中顺序排列)。
完美子序列:任意相邻两数之间的差不大于d。长度大于等于2。
思路
树状数组优化dp:
dp[i] = sum(dp[j]), i - d <= j <= i + d;
dp[i]++; (dp中应包括自身长度为1的子序列,但不加到答案上)
数列范围为整形(包括负),范围过大应用树状数组应该离散化。STL: unique(), lower_bound()
HINT
答案取模,程序中注意谨慎地处处取模,以及(a + mod) % mod,防止出现负数。
#include <iostream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#define MAX 1000000
#define MAXN 100002
using namespace std;
long long sum[MAX];
int a[MAXN], cnt;
const int mod = 9901;
int lowbit(int x)
{
return x & (-x);
}
void update(int i, long long val)
{
while (i <= cnt)
{
sum[i] = (sum[i] + val) % mod;
i += lowbit(i);
}
}
long long getSum(int x)
{
long long s = 0;
while (x > 0)
{
s = (s + sum[x]) % mod;
x -= lowbit(x);
}
return s;
}
int t[MAX];
int main()
{
//freopen("aa.txt", "r", stdin);
int n, d, result;
while (scanf("%d %d", &n, &d) != EOF && n)
{
int tail = 0, upper, lower;
result = 0;
memset(sum, 0, sizeof(sum));
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
t[tail++] = a[i];
}
sort(t, t + tail);
cnt = unique(t, t + tail) - t;
lower = t[0];
upper = t[cnt - 1];
for (int i = 0; i < n; i++)
{
int l, r;
if ((long long)a[i] - d <= lower)
l = 0;
else
l = lower_bound(t, t + cnt, a[i] - d) - t;
if ((long long)a[i] + d > upper)
r = cnt;
else
{
r = lower_bound(t, t + cnt, a[i] + d) - t;
if (t[r] == a[i] + d)
r++;
}
long long temp = (getSum(r) - getSum(l) + mod) % mod;
result += temp;
result %= mod;
update(lower_bound(t, t + cnt, a[i]) - t + 1, temp + 1);
}
cout << result << endl;
}
}