树状数组求逆序对
2016-08-07 11:11
344 查看
逆序对
题目描述给定一个数组A,它包含N个整数, 分别是A[1],A[2],...A。如果存在下标i和j,使得 i < j 且 A[i]>A[j]同时成立,则(i,j)就为一个“逆序对”。
那么A数组总共有多少对不同的“逆序对”?输入格式 1247.in第一行为n(1≤n≤100000)。
接下来是n行,每行一个长整型范围内的整数。输出格式 1247.out一个整数,为逆序对的数目。输入样例 1247.in5
3
1
4
5
2输出样例 1247.out4
各测试点信息
测试点编号 | 测试点分数 | 测试点时限 | 测试点内存 |
1 | 10 | 1 | 128 |
2 | 10 | 1 | 128 |
3 | 10 | 1 | 128 |
4 | 10 | 1 | 128 |
5 | 10 | 1 | 128 |
6 | 10 | 1 | 128 |
7 | 10 | 1 | 128 |
8 | 10 | 1 | 128 |
9 | 10 | 1 | 128 |
10 | 10 | 1 | 128 |
//by LKB 2016.8.5
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
#define lowbit(x) (x&(-x))
const int maxn = 1e5 + 9;
struct Tnode {
int x, y;
Tnode() {
x = y = 0;
}
} a[maxn]; //离散化时用
int n;
int b[maxn]; //离散后的数组
int tree[maxn]; //树状数组
bool cmp(Tnode i, Tnode j) {
return i.x < j.x;
}
void update(int k) { //单点修改
while(k <= n) {
++tree[k];
k += lowbit(k);
}
}
int query(int k) { //区间求和
int sum = 0;
while(k) {
sum += tree[k];
k -= lowbit(k);
}
return sum;
}
int main() {
freopen("1247.in", "r", stdin);
freopen("1247.out", "w", stdout);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i].x;
a[i].y = i - 1;
}
//离散化
sort(a + 1, a + n + 1, cmp);
int now = 0;
for(int i = 1; i <= n; i++) {
if(i == 0 || a[i].x != a[i - 1].x) ++now;
b[a[i].y] = now;
}
long long ans = 0; //注意答案最多可能是n平方级的,要开long long
for(int i = 0; i < n; i++) {
ans += (i - query(b[i])); //求在自己的前面有多少比自己大的数
update(b[i]); //维护树状数组,加入当前值
}
cout << ans << endl;
return 0;
}
相关文章推荐
- POJ 3254 - Corn Fields
- 【[usaco1.3] 滑雪课程设计 Ski Course Design 】【枚举】
- 爆裂吧世界(world/1S/64M)
- 夏令营day1总结
- 波老师(teacher/1S/64M)
- 音阶(ljestvica/1S/64M)
- NOIP2004火星人
- LAMP - Apache访问控制
- 【洛谷1211 [USACO1.3]牛式 Prime Cryptarithm】【枚举】
- 白书刷题记录
- 后台开发面试 linux os
- 2016 年大沥镇小学青少年信息学奥林匹克竞赛反思(甲乙组)
- 第三周小结+赛前最终总结(4.24~4.27)
- hdu 5781 ATM Mechine 概率(期望)dp
- STL之pair
- USACO 2016 JANUARY CONTEST, BRONZE PROBLEM 3. MOWING THE FIELD(收割庄稼)
- USACO 2016 JANUARY CONTEST, BRONZE PROBLEM 1. PROMOTION COUNTING
- gdoi2009中山市选T2 小球
- gdoi2009中山市选T1 谁能赢呢?
- usaco2016open gold3 248