HDOJ 3450 HDU 3450 Counting Sequences ACM 3450 IN HDU
2010-08-30 09:59
531 查看
MiYu原创, 转帖请注明 : 转载自 ______________白白の屋
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=3450
题目描述:
Total Submission(s): 312 Accepted Submission(s): 105
[align=left]Problem Description[/align]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.
[align=left]Input[/align]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
[align=left]Output[/align]The number of Perfect Sub-sequences mod 9901
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
题目分析 :
( 线段树 || 树状数组 ) + DP
可以使用线段树 或 树状数组来做, 可惜本人现在还不会线段树, 下面是 树状数组 解题的分析 :
因为题目要求的 是 k >= 2 , 而且 相邻元素 之差的绝对值 不大于 d, 这里纠结了很久 , 一直没明白 "and the
neighboring 2 elements have the difference not larger than d" 这句话的意思, 英语水平太差了. 最后在
Amb 的解释下才明白, 0rz...........
为了使问题简单化, 我们不凡讨论 k >= 1 的情况:
因为 输入数据的范围比较大, 2<=n<=100000,1<=d=<=10000000 , 所以先要将 数据排序后 用 hash[max] 做离散化处理.
当然, 原数组需要另开一个数组保存起来. 处理完成后, 我们可以这样理解 : 用树状数组 com[pos], ( pos 为 num 在 hash 数组中的位
置 ) . 记录 能与 num 构成 完美串的个数. 初始状态的 完美子串 为0, 每次加入一个数, 那么这个数 num 与 比他小且差不超过d的第一
个数 而且与 比他大且差不超过d的第一个数 构成完美串 . 更新树状数组. 最后求出所有的子串和 sum, 因为算法是以 k >= 1 来做的,而
题目要求 k >= 2, 也就是说, 对 N 个数, 就多计算了 N 次, 因此 (sum - N ) % 9901 即为所求. ( 别忘了MOD....... )
代码如下 :
/*MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 http://www.cnblog.com/MiYuAuthor By : MiYuTest : 1Program : 3450*/
#include <iostream>#include <algorithm>using namespace std;const int MAX = 100010;const int MOD = 9901;int nCount = 0;int com[MAX];int hash[MAX];int num1[MAX];int num2[MAX];int N,D;inline int low ( int x ) { return x & ( -x );}void modify ( int x, int val ){ // 修改 while ( x <= nCount ){ com[x] += val; x += low ( x ); } }int quy ( int x ){ // 查询 int sum = 0; while ( x > 0 ){ sum += com[x]; x -= low ( x ); } return sum ;}int find1 ( int val ){ // 二分 找 <= val 的第一个数 int beg = 1, end = nCount; int mid = ( beg + end ) >> 1; int res = mid; while ( beg <= end ){ if ( hash[mid] <= val ){ beg = mid + 1; res = mid; }else{ end = mid - 1; } mid = ( beg + end ) >> 1; } return res;}int find2 ( int val ){ // 二分 找 <= val 的第一个数 int beg = 1, end = nCount; int mid = ( beg + end ) >> 1; int res = mid; while ( beg <= end ){ if ( hash[mid] < val ){ beg = mid + 1; }else{ end = mid - 1; res = mid; } mid = ( beg + end ) >> 1; } return res;}inline bool scan_d(int &num) // 输入 { char in;bool IsN=false; in=getchar(); if(in==EOF) return false; while(in!='-'&&(in<'0'||in>'9')) in=getchar(); if(in=='-'){ IsN=true;num=0;} else num=in-'0'; while(in=getchar(),in>='0'&&in<='9'){ num*=10,num+=in-'0'; } if(IsN) num=-num; return true;}int main (){ while ( scan_d ( N ) && scan_d ( D ) ){ for ( int i = 0; i < N; ++ i ){ scan_d ( num1[i] ); num2[i] = num1[i]; } sort ( num1, num1 + N ); hash[1] = num1[0]; nCount = 1; for ( int i = 1; i < N; ++ i ){ // 数据 离散化 if ( num1[i] != num1[i-1] ) hash[++nCount] = num1[i]; } memset ( com, 0, sizeof ( com ) ); for ( int i = 0; i < N; ++ i ){ int pos = find1 ( num2[i] ); // 找当前元素的 hash 下标 int pre = find1 ( num2[i] + D ); // 找 <= num2[i] + D 的第一个数 int tail = find2 ( num2[i] - D ); // 找 >= num2[i] - D 的第一个数 int val = quy ( pre ) - quy ( tail - 1 ) + 1; // 区间 [ num2[i] - D, num2[i] + D ] 的元素个数 + 新增的一个元素 modify ( pos, val % MOD ); } cout << ( quy ( nCount ) - N ) % MOD << endl; //以 一个元素 的 [ elem - D, elem + D ] 计算, 题目要求 k >= 2, 减掉 N 个 } return 0;}
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=3450
题目描述:
Counting Sequences
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others)Total Submission(s): 312 Accepted Submission(s): 105
[align=left]Problem Description[/align]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.
[align=left]Input[/align]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
[align=left]Output[/align]The number of Perfect Sub-sequences mod 9901
[align=left]Sample Input[/align]
4 2 1 3 7 5
[align=left]Sample Output[/align]
4
题目分析 :
( 线段树 || 树状数组 ) + DP
可以使用线段树 或 树状数组来做, 可惜本人现在还不会线段树, 下面是 树状数组 解题的分析 :
因为题目要求的 是 k >= 2 , 而且 相邻元素 之差的绝对值 不大于 d, 这里纠结了很久 , 一直没明白 "and the
neighboring 2 elements have the difference not larger than d" 这句话的意思, 英语水平太差了. 最后在
Amb 的解释下才明白, 0rz...........
为了使问题简单化, 我们不凡讨论 k >= 1 的情况:
因为 输入数据的范围比较大, 2<=n<=100000,1<=d=<=10000000 , 所以先要将 数据排序后 用 hash[max] 做离散化处理.
当然, 原数组需要另开一个数组保存起来. 处理完成后, 我们可以这样理解 : 用树状数组 com[pos], ( pos 为 num 在 hash 数组中的位
置 ) . 记录 能与 num 构成 完美串的个数. 初始状态的 完美子串 为0, 每次加入一个数, 那么这个数 num 与 比他小且差不超过d的第一
个数 而且与 比他大且差不超过d的第一个数 构成完美串 . 更新树状数组. 最后求出所有的子串和 sum, 因为算法是以 k >= 1 来做的,而
题目要求 k >= 2, 也就是说, 对 N 个数, 就多计算了 N 次, 因此 (sum - N ) % 9901 即为所求. ( 别忘了MOD....... )
代码如下 :
/*MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 http://www.cnblog.com/MiYuAuthor By : MiYuTest : 1Program : 3450*/
#include <iostream>#include <algorithm>using namespace std;const int MAX = 100010;const int MOD = 9901;int nCount = 0;int com[MAX];int hash[MAX];int num1[MAX];int num2[MAX];int N,D;inline int low ( int x ) { return x & ( -x );}void modify ( int x, int val ){ // 修改 while ( x <= nCount ){ com[x] += val; x += low ( x ); } }int quy ( int x ){ // 查询 int sum = 0; while ( x > 0 ){ sum += com[x]; x -= low ( x ); } return sum ;}int find1 ( int val ){ // 二分 找 <= val 的第一个数 int beg = 1, end = nCount; int mid = ( beg + end ) >> 1; int res = mid; while ( beg <= end ){ if ( hash[mid] <= val ){ beg = mid + 1; res = mid; }else{ end = mid - 1; } mid = ( beg + end ) >> 1; } return res;}int find2 ( int val ){ // 二分 找 <= val 的第一个数 int beg = 1, end = nCount; int mid = ( beg + end ) >> 1; int res = mid; while ( beg <= end ){ if ( hash[mid] < val ){ beg = mid + 1; }else{ end = mid - 1; res = mid; } mid = ( beg + end ) >> 1; } return res;}inline bool scan_d(int &num) // 输入 { char in;bool IsN=false; in=getchar(); if(in==EOF) return false; while(in!='-'&&(in<'0'||in>'9')) in=getchar(); if(in=='-'){ IsN=true;num=0;} else num=in-'0'; while(in=getchar(),in>='0'&&in<='9'){ num*=10,num+=in-'0'; } if(IsN) num=-num; return true;}int main (){ while ( scan_d ( N ) && scan_d ( D ) ){ for ( int i = 0; i < N; ++ i ){ scan_d ( num1[i] ); num2[i] = num1[i]; } sort ( num1, num1 + N ); hash[1] = num1[0]; nCount = 1; for ( int i = 1; i < N; ++ i ){ // 数据 离散化 if ( num1[i] != num1[i-1] ) hash[++nCount] = num1[i]; } memset ( com, 0, sizeof ( com ) ); for ( int i = 0; i < N; ++ i ){ int pos = find1 ( num2[i] ); // 找当前元素的 hash 下标 int pre = find1 ( num2[i] + D ); // 找 <= num2[i] + D 的第一个数 int tail = find2 ( num2[i] - D ); // 找 >= num2[i] - D 的第一个数 int val = quy ( pre ) - quy ( tail - 1 ) + 1; // 区间 [ num2[i] - D, num2[i] + D ] 的元素个数 + 新增的一个元素 modify ( pos, val % MOD ); } cout << ( quy ( nCount ) - N ) % MOD << endl; //以 一个元素 的 [ elem - D, elem + D ] 计算, 题目要求 k >= 2, 减掉 N 个 } return 0;}
相关文章推荐
- HDOJ HDU 2673 shǎ崽 OrOrOrOrz ACM 2673 IN HDU
- HDOJ HDU 1023 1130 1133 1134 2067 ACM 1023 1130 1133 1134 2067 IN HDU ( 卡特兰数 专题 catalan )
- HDOJ HDU 2149 Public Sale ACM 2149 IN HDU
- HDOJ 1406 HDU 1406 完数 ACM 1406 IN HDU
- HDOJ 2526 HDU 2526 浪漫手机 ACM 2526 IN HDU
- HDOJ HDU 2068 RPG的错排 ACM 2068 IN HDU
- HDOJ HDU 1133 Buy the Ticket ACM 1133 IN HDU
- HDU 2795 HDOJ 2795 Billboard ACM 2795 IN HDU
- HDOJ HDU 1171 Big Event ACM 1171 IN HDU
- HDOJ HDU 2086 A1 = ? ACM 2086 IN HDU
- HDOJ HDU 1202 The calculation of GPA ACM 202 IN HDU
- HDOJ HDU 1272 小希的迷宫 ACM 1272 IN HDU
- HDOJ 1286 HDU 1286 找新朋友 ACM 1286 IN HDU
- HDU 2561 HDOJ 2561 第二小整数 ACM 2561 IN HDU
- HDOJ HDU 1856 More is better ACM 1856 IN HDU
- HDOJ 2544 HDU 2544 最短路 ACM 2544 IN HDU
- HDU 1711 HDOJ 1711 Number Sequence ACM 1711 IN HDU
- HDOJ HDU 1028 Ignatius and the Princess III ACM 1028 IN HDU
- HDOJ 1213 HDU 1213 How Many Tables ACM 1213 IN HDU
- HDOJ 2066 HDU 2066 一个人的旅行 ACM 2066 IN HDU