Counting Sequences |
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others) |
Total Submission(s): 116 Accepted Submission(s): 41 |
Problem Description
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.
|
Input
Multiple test cases The first line will contain 2 integers n, d(2<=n<=100000,1<=d=<=10000000) The second line n integers, representing the suquence
|
Output
The number of Perfect Sub-sequences mod 9901
|
Sample Input
4 2 1 3 7 5 |
Sample Output
4 |
Source
2010 ACM-ICPC Multi-University Training Contest(2)——Host by BUPT
|
分析:树状数组+DP。sort再用map离散化后,二分找到每个数与他绝对值差小于等于d的数的下标范围。进行dp时,用树状数组对该范围求和并保证结果为正数。
#include <cstdlib> #include <cstring> #include <cstdio> #include <map> #include <algorithm> #define MOD 9901 #define MAXN 100005 using namespace std; int a[MAXN], b[MAXN], c[MAXN], left[MAXN], right[MAXN], cnt; inline int lowbit(int x) { return x & -x; } inline void add(int pos, int val) { for (int i = pos; i <= cnt; i += lowbit(i)) { c[i] += val; if (c[i] >= MOD) c[i] %= MOD; } } inline int sum(int pos) { int s = 0; for (int i = pos; i > 0; i -= lowbit(i)) { s += c[i]; if (s >= MOD) s %= MOD; } return s; } int main() { int n, i, x, d, t, m, l, r; long long T; int ans; while (scanf("%d%d", &n, &d) != EOF) { for (i = 0; i < n; ++i) { scanf("%d", &a[i]); b[i + 1] = a[i]; } memset(c, 0, sizeof (c)); map <int, int> mymap; sort(b + 1, b + n + 1); cnt = unique(b + 1, b + n + 1) - b - 1; for (i = 1; i <= cnt; ++i) { mymap[b[i]] = i; t = b[i] - d; if (b[1] >= t) { left[i] = 1; goto L; } l = 1; r = i; while (r - l > 1) { m = (r + l) >> 1; if (b[m] < t) l = m; else if (b[m] > t) r = m; else { left[i] = m; goto L; } } left[i] = r; L: T = b[i] + d; if (b[cnt] <= T) { right[i] = cnt; goto R; } l = i; r = cnt; while (r - l > 1) { m = (l + r) >> 1; if (b[m] > T) r = m; else if (b[m] < T) l = m; else { right[i] = m; goto R; } } right[i] = l; R: ; } ans = 0; for (i = 0; i < n; ++i) { t = mymap[a[i]]; x = sum(right[t]) - sum(left[t] - 1); if (x < 0) x += MOD; ans += x; if (ans >= MOD) ans %= MOD; add(t, (x + 1)%MOD); } printf("%d\n", ans); } return 0; }