Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0总体思路:
由于a[i]的范围太大,故不可能以a[i]的值为下标创建树状数组,需要进行离散化处理。离散化处理的结果要求和原有数据的次序保持一致,这样我们就可以用离散化处理后的结果来代替原有的数据进行相关计算。离散化处理的主要步骤如下:
struct Node { int val; int pos; }; Node node[MAXN]; int reflect[MAXN]; sort(node, node + MAXN, cmp)//按实际情况进行处理 reflect[node[i].pos] = i; //val存放原数组的元素,pos存放原始位置,即node[i].pos = i。 //把这些结构体按照val的大小排序。 //reflect数组存放离散化后的值,即reflect[node[i].pos] = i。 //这样从头到尾读入reflect数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。
处理好后reflect数组的次序和原有数据的次序保持一致,因此可以代替原有的数据进行相关计算。
代码如下:
#include<iostream> #include<vector> #include<string> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 500010; int a[MAXN]; int n; int lowbit(int t) { return t&(-t); } void update(int t, int d) { while (t <= n) { a[t] += d; t += lowbit(t); } } long long getsum(int t) { long long sum(0); while (t > 0) { sum += a[t]; t -= lowbit(t); } return sum; } struct Node { int val; int pos; }; bool cmp(Node& lhs, Node& rhs) { return lhs.val < rhs.val; } Node node[MAXN]; int reflect[MAXN]; int main() { #ifdef ONLINE_JUDGE #else freopen("D:\\in.txt", "r", stdin); freopen("D:\\out.txt", "w", stdout); #endif while (scanf("%d", &n) != EOF) { if (n == 0) break; memset(a, 0, sizeof(a)); for (int i = 1; i <=n; i++) { scanf("%d", &node[i].val); node[i].pos = i; } sort(node+1, node + n+1, cmp);//注意排序的范围 for (int i = 1; i <= n; i++) { //reflect[i] = node[i].pos; reflect[node[i].pos] = i;//离散化处理,原有序列的排名 } long long ans(0); //现在总共有j个数,getsum(a[j])为比a[j]小的数的个数加1, //则比a[j]大的数的个数为j-getsum(a[j]); for (int i = 1; i <= n; i++) { update(reflect[i], 1); //ans += (i - getsum(a[i])); //这个地方要注意理解 ans += (i - getsum(reflect[i])); } printf("%lld\n", ans); } return 0; }