hdu Counting Sequences

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;
}

 

posted @ 2012-09-16 00:51  YogyKwan  阅读(191)  评论(0编辑  收藏  举报