hdu3450
分析:首先要知道有递推公式dp[i] = Sigma(dp[j]),dp[i]表示第i个数结尾的完美子序列的个数,|a[i] - a[j]| <= d,j<i。直接这样做的时间复杂度为n^2,对于最大有100000的n还是会超时的,留意到公式是连续加的(j<i 时,以[a[i] - d, a[i] + d]区间里面的数结尾的完美子序列个数相加),其实j>i的[a[i] - d, a[i] + d]区间里面的数结尾的完美子序列个数也可以加进去,只要初始化都为0,正因为这样可以用树状数组对这种加法进行加速,只要先用二分查找出区间两端点对应在树状数组里面的下标。
1 #pragma warning(disable:4996) 2 #include <cstdio> 3 #include <set> 4 #include <stack> 5 #include <vector> 6 #include <algorithm> 7 #include <map> 8 #define MOD 9901 9 using namespace std; 10 int bit[100005];//bit -- binary indexed tree 11 int a[100005], order[100005], len; 12 int lowBit(int x){ 13 return x & (-x); 14 } 15 //size是数组的大小,val是增量 16 void update(int idx, int size, int val){ 17 while (idx <= size){ 18 bit[idx] += val; 19 if (bit[idx] >= MOD){ 20 bit[idx] %= MOD; 21 } 22 idx += lowBit(idx); 23 } 24 } 25 //求a[1]到a[idx]的连续子序列的和 26 int sum(int idx){ 27 int ret = 0; 28 while (idx > 0){ 29 ret += bit[idx]; 30 if (ret >= MOD){ 31 ret %= MOD; 32 } 33 idx -= lowBit(idx); 34 } 35 return ret; 36 } 37 int main(){ 38 int n, d, len; 39 while (~scanf("%d%d", &n, &d)){ 40 for (int i = 1; i <= n; i++){ 41 scanf("%d", &a[i]); 42 } 43 copy(a + 1, a + 1 + n, order + 1); 44 sort(order + 1, order + 1 + n); 45 len = unique(order + 1, order + 1 + n) - order - 1; 46 memset(bit, 0, sizeof(bit)); 47 for (int i = 1; i <= n; i++){ 48 int r = upper_bound(order + 1, order + 1 + len, a[i] + d) - order - 1; 49 int l = lower_bound(order + 1, order + 1 + len, a[i] - d) - order - 1; 50 int p = lower_bound(order + 1, order + 1 + len, a[i]) - order; 51 int temp = sum(r) - sum(l); 52 temp = (temp % MOD + MOD) % MOD; 53 update(p, len, temp + 1); 54 } 55 printf("%d\n", ((sum(len) - n) % MOD + MOD) % MOD); 56 } 57 return 0; 58 }