《算法竞赛-训练指南》第三章-3.7_LA 3429(树状数组)
2013-09-02 21:08
246 查看
树状数组的题目还是说比较简单的吧,主要就是解决动态更新求和的问题。主要运用到的就是lowbit的翻倍求和思想。编码很少,但是主要是思想。一看出现:动态的修改单个元素并求前缀和的题目那就是用树状数组解决此问题的。
别的不多讲了,这道题目还是比较不错的,将的是给你N个不相同的Ai,问你两个一小一大的Ai夹这一个中等的Ai的情况有多少种。解题想法是这样的,既然要求是不相等的,而且A的范围不大,可以想到用hash标记,然后求的同时动态的更新小于Ai的值,很明显就是树状数组了,由此可解。
贴出代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 100022;
int A[20022];
int C[100011];
int D[100011];
int t[100011];
int N;
int lowbit(int x)
{
return x & (-x);
}
void add(int j, int x)
{
for (int i = j; i < MAXN; i += lowbit(i))
{
t[i] += x;
}
}
int sum(int j)
{
int sum = 0;
for (int i = j; i > 0; i -= lowbit(i))
{
sum += t[i];
}
return sum;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &N);
for (int i = 1; i <= N; i++)
{
scanf("%d", &A[i]);
}
memset(t, 0, sizeof(t));
for (int i = 1; i <= N; i++)
{
add(A[i], 1);
C[i] = sum(A[i] - 1);
}
/*
for (int i = 0; i <= N; i++)
{
printf("C[%d] = %d\n", i, C[i]);
}
*/
memset(t, 0, sizeof(t));
for (int i = N; i >= 1; i--)
{
add(A[i], 1);
D[i] = sum(A[i] - 1);
}
/*
for (int i = 0; i <= N; i++)
{
printf("D[%d] = %d\n", i, D[i]);
}
*/
long long sum = 0;
for (int i = 1; i <= N; i++)
{
sum += (long long)C[i] * (N - i - D[i]) + (long long)(D[i]) * (i - 1 - C[i]);
// cout << sum << endl;
}
printf("%lld\n", sum);
}
// system("pause");
return 0;
}
别的不多讲了,这道题目还是比较不错的,将的是给你N个不相同的Ai,问你两个一小一大的Ai夹这一个中等的Ai的情况有多少种。解题想法是这样的,既然要求是不相等的,而且A的范围不大,可以想到用hash标记,然后求的同时动态的更新小于Ai的值,很明显就是树状数组了,由此可解。
贴出代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
const int MAXN = 100022;
int A[20022];
int C[100011];
int D[100011];
int t[100011];
int N;
int lowbit(int x)
{
return x & (-x);
}
void add(int j, int x)
{
for (int i = j; i < MAXN; i += lowbit(i))
{
t[i] += x;
}
}
int sum(int j)
{
int sum = 0;
for (int i = j; i > 0; i -= lowbit(i))
{
sum += t[i];
}
return sum;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d", &N);
for (int i = 1; i <= N; i++)
{
scanf("%d", &A[i]);
}
memset(t, 0, sizeof(t));
for (int i = 1; i <= N; i++)
{
add(A[i], 1);
C[i] = sum(A[i] - 1);
}
/*
for (int i = 0; i <= N; i++)
{
printf("C[%d] = %d\n", i, C[i]);
}
*/
memset(t, 0, sizeof(t));
for (int i = N; i >= 1; i--)
{
add(A[i], 1);
D[i] = sum(A[i] - 1);
}
/*
for (int i = 0; i <= N; i++)
{
printf("D[%d] = %d\n", i, D[i]);
}
*/
long long sum = 0;
for (int i = 1; i <= N; i++)
{
sum += (long long)C[i] * (N - i - D[i]) + (long long)(D[i]) * (i - 1 - C[i]);
// cout << sum << endl;
}
printf("%lld\n", sum);
}
// system("pause");
return 0;
}
相关文章推荐
- 《算法竞赛-训练指南》第三章-3.6_LA 3027(并查集)
- 《算法竞赛-训练指南》第三章-3.8_UVa 11235
- 《算法竞赛-训练指南》第二章-2.28_LA 3485(simpson)
- 《算法竞赛-训练指南》第一章-1.4_LA 3708
- 《算法竞赛-训练指南》第一章-1.26_LA 3882
- 《算法竞赛-训练指南》第一章-1.12_LA 3971
- 《算法竞赛-训练指南》第一章-1.15_LA 3902
- 《算法竞赛-训练指南》第一章-1.24_pre-一维数组最大连续和
- 《算法竞赛-训练指南》-第三章-Trie
- 《算法竞赛-训练指南》第三章-RMQ
- 《算法竞赛-训练指南》第一章-1.13_LA 3635
- 《算法竞赛-训练指南》第一章-1.20_LA 3905
- 《算法竞赛-训练指南》第一章-1.22_LA 3209
- 《算法竞赛-训练指南》第三章-2.2_UVa 11991
- 《算法竞赛-训练指南》第二章-2.12_LA 5059
- 《算法竞赛-训练指南》第二章-2.27_LA 5009
- 《算法竞赛-训练指南》第一章-1.25-LA 2965
- 《算法竞赛-训练指南》第二章-2.4-LA 3516
- 《算法竞赛-训练指南》第一章-1.23_LA 3695
- 《算法竞赛-训练指南》第一章-1.16_LA 3177