CSU 1515: Sequence

来源:互联网 发布:软件设计师 考试 编辑:程序博客网 时间:2024/05/23 19:23

题目:

Description

Give you a sequence consisted of n numbers. You are required to answer how many pairs of numbers (ai, aj) satisfy that | ai - aj | = 1 and L ≤ i < j ≤ R.

Input

The input consists of one or more test cases.
For each case, the first line contains two numbers n and m, which represent the length of the number sequence and the number of queries. ( 1 ≤ n ≤ 10^4, 1 ≤ m ≤ 10^5 )
The second line consists of n numbers separated by n - 1 spaces.( 0 ≤ ai < 2^31 )
Then the m lines followed each contain two values Li and Ri.

Output

For each case just output the answers in m lines.

Sample Input

10 105 5 1 3 6 3 5 7 1 73 46 88 92 85 76 71 93 103 105 6

Sample Output

0003104330

这个题目我就是用动态规划来做的。

递推式是:

r[i][j] = r[i + 1][j] - r[i + 1][j - 1] + r[i][j - 1];if (list[i] - list[j] == 1 || list[i] - list[j] == -1)r[i][j]++;

不过有1个问题,n有1万,1万乘以1万的数组不仅仅是超题目给的内存,而是直接就runtime error了。

错误代码:

#include<iostream>#include<string.h>using namespace std;int list[10001];int r[10001][10001];int main(){int n, m;int start, endd;memset(r, 0, sizeof(r));while (cin >> n >> m){for (int i = 1; i <= n; i++)cin >> list[i];for (int j = 2; j <= n; j++){for (int i = j - 1; i >= 1; i--){r[i][j] = r[i + 1][j] - r[i + 1][j - 1] + r[i][j - 1];if (list[i] - list[j] == 1 || list[i] - list[j] == -1)r[i][j]++;}}while (m--){cin >> start >> endd;cout << r[start][endd] << endl;}}return 0;}

于是我只好把r变成1000*1000的数组。

这样,r就只能存储那些2个小标都是10的倍数的区间。

在计算这个r时,递推式略有变化。

假如a<b<c<d,用f来表示最后要求的那个答案,即要输出的数,那么,

f(a,d)=f(a,c)+f(b,d)-f(b,c)+x,其中x是从a到b的区间中选1个数,从c到d的区间选1个数,一共有多少对数满足条件。

在本题里面,用g函数计算x,不过递推式没有上述的递推式那么广泛,

因为仍然是用动态规划做的,所以b-a都是10或者0,d-c都是10或者0。

注意,实际上abcd并不是严格递增的,所以g函数里面sum++的条件必须有i<j

正确的代码:

#include<iostream>#include<string.h>#include<math.h>using namespace std;int list[10001];int r[1001][1001];int g(int s,int e){int sum = 0;for (int i = s; i < s + 10;i++)for (int j = e; j>e - 10;j--)if (i < j && list[i] == list[j] + 1 || list[i] == list[j] - 1)sum++;return sum;}int main(){int n, m;int s, e;int s10, e10;int sum;memset(r, 0, sizeof(r));while (cin >> n >> m){for (int i = 0; i < n; i++)cin >> list[i];for (int j = 1; j <= (n - 1) / 10; j++)for (int i = j - 1; i >= 0; i--)r[i][j] = r[i + 1][j] - r[i + 1][j - 1] + r[i][j - 1] + g(i * 10, j * 10);while (m--){cin >> s >> e;s--;e--;s10 = (s + 9) / 10;e10 = e / 10;sum = r[s10][e10];for (int i = s; i < s10 * 10; i++)for (int j = i + 1; j <= e; j++)if (list[i] == list[j] + 1 || list[i] == list[j] - 1)sum++;for (int j = e10 * 10 + 1; j <= e; j++)for (int i = s10 * 10; i < j;i++)if (list[i] == list[j] + 1 || list[i] == list[j] - 1)sum++;cout << sum << endl;}}return 0;}

1 0