Counting Sequences
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others)Total Submission(s): 1158 Accepted Submission(s): 397
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
代码:
#include<stdio.h>
#include <algorithm>
using namespace std;
#define N 100010
#define MOD 9901
#define lowbit(x) (x&(-x))
#include <algorithm>
using namespace std;
#define N 100010
#define MOD 9901
#define lowbit(x) (x&(-x))
int cnt;
int p[N];
int hash[N];
int a[N];
int b[N];
int n,d;
int p[N];
int hash[N];
int a[N];
int b[N];
int n,d;
int find1 ( int x ) //二分找 <=x的第一个数;
{
int l= 1;
int r= cnt;
int m= (l+r) /2;
int rec= m;
while ( l<=r )
{
if ( hash[m] <= x )
{
l= m+ 1;
rec= m;
}
else
{
r= m - 1;
}
m = ( l+r ) / 2;
}
return rec;
}
int find2 ( int x )// 二分找 >= x的第一个数;
{
int l= 1;
int r= cnt;
int m = ( l+r) /2 ;
int rec = m;
while (l<=r)
{
if ( hash[m] < x )
{
l = m+ 1;
}
else
{
r = m - 1; rec = m;
}
m = ( l+r)/2;
}
return rec;
}
int quy ( int x )// 查询 ;
{
int sum = 0;
while ( x > 0 )
{
sum += p[x];
x -= lowbit ( x );
}
return sum ;
}
void modify ( int a, int b )// 修改;
{
while ( a<= cnt )
{
p[a] +=b;
a+= lowbit ( a );
}
}
{
int l= 1;
int r= cnt;
int m= (l+r) /2;
int rec= m;
while ( l<=r )
{
if ( hash[m] <= x )
{
l= m+ 1;
rec= m;
}
else
{
r= m - 1;
}
m = ( l+r ) / 2;
}
return rec;
}
int find2 ( int x )// 二分找 >= x的第一个数;
{
int l= 1;
int r= cnt;
int m = ( l+r) /2 ;
int rec = m;
while (l<=r)
{
if ( hash[m] < x )
{
l = m+ 1;
}
else
{
r = m - 1; rec = m;
}
m = ( l+r)/2;
}
return rec;
}
int quy ( int x )// 查询 ;
{
int sum = 0;
while ( x > 0 )
{
sum += p[x];
x -= lowbit ( x );
}
return sum ;
}
void modify ( int a, int b )// 修改;
{
while ( a<= cnt )
{
p[a] +=b;
a+= lowbit ( a );
}
}
int main ()
{
while (scanf("%d%d",&n,&d)!=-1)
{
for ( int i = 0; i < n; ++ i ){
scanf("%d",&a[i]);
b[i] = a[i];
}
memset ( p, 0, sizeof(p) );
sort ( a, a+n);
hash[1] = a[0];
cnt = 1;
for ( int i = 1; i < n; ++ i )// 数据离散化;
{
if ( a[i] != a[i-1] )
hash[++cnt] = a[i];
}
for ( int i = 0; i < n; ++ i )
{
int pos = find1 ( b[i] ); // 找当前元素的 hash下标;
int pre = find1 ( b[i] + d ); // 找 <=b[i] + d的第一个数;
int tail = find2 ( b[i] - d ); // 找 >=b[i]-d的第一个数;
int val = quy ( pre ) - quy ( tail - 1 ) + 1; // 区间[b[i]-d,b[i]+d]的元素个数+新增的一个元素(本身);
modify ( pos, val%MOD );
}
printf( "%d\n",( quy ( cnt ) - n ) % MOD); //以一个元素的[elem-d,elem+d]计算,题目要求k>=2,减掉 n个;
}
return 0;
}
{
while (scanf("%d%d",&n,&d)!=-1)
{
for ( int i = 0; i < n; ++ i ){
scanf("%d",&a[i]);
b[i] = a[i];
}
memset ( p, 0, sizeof(p) );
sort ( a, a+n);
hash[1] = a[0];
cnt = 1;
for ( int i = 1; i < n; ++ i )// 数据离散化;
{
if ( a[i] != a[i-1] )
hash[++cnt] = a[i];
}
for ( int i = 0; i < n; ++ i )
{
int pos = find1 ( b[i] ); // 找当前元素的 hash下标;
int pre = find1 ( b[i] + d ); // 找 <=b[i] + d的第一个数;
int tail = find2 ( b[i] - d ); // 找 >=b[i]-d的第一个数;
int val = quy ( pre ) - quy ( tail - 1 ) + 1; // 区间[b[i]-d,b[i]+d]的元素个数+新增的一个元素(本身);
modify ( pos, val%MOD );
}
printf( "%d\n",( quy ( cnt ) - n ) % MOD); //以一个元素的[elem-d,elem+d]计算,题目要求k>=2,减掉 n个;
}
return 0;
}