【a703】求逆序对(树状数组的解法)
Time Limit: 10 second
Memory Limit: 2 MB
问题描述
给定一个序列a1,a2...an。如果存在i小于j 并且ai大于aj,那么我们称之为逆序对,求给定序列中逆序对的数目
Input
第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
Output
所有逆序对的总数
Sample Input
4
3
2
3
2
Sample Output
3
【题解】
这题的n最大值为10w.
求逆序对的方法除了利用归并排序之外,还可以用树状数组来解决。
以下是方法。
比如
3 2 8 5
将它们排序(从大到小)
8 5 3 2
先把8放进去(原来的位置是3)
但是在放之前,先检查位置3之前有没有其他数字放进去了(如果放进去了肯定是比8大的数字,但是它们的下标又小于3(逆序对!));
因为没有
所以就把下标3对应的树状数组改为1;
即0 0 1 0
然后是第大的5(原来的位置是4)
则看看4前面有多少个元素已经放进去了(前缀和!)。
发现有1个。则答案递增1;
然后把tree_arr[4] 改为1
即0 0 1 1
然后是第三大的数字3,它原来的位置是1,但是1前面没有数字已经放进去。则不递增答案。
最后是最小的元素2,它原来的位置就是2,然后位置2之前有一个数字3已经放在了位置1.即下标1的前缀和为1.则答案递增1.
最后答案为2;
而树状数组就是专门处理前缀和的。
排序完毕之后,从大到小,从他们各自原来的位置,一直往左累加长条(前缀和)就可以了。然后累加完毕之后,需要把它放在原来的位置(置为1),则又要往右更新了。
但是要注意一个问题。就是出现相同数字的情况。
则我们在写比较函数的时候,让相同的数字,之前的位置大的放在后面。然后我们处理到连续的相同数字的时候。就记录这是连续相同数字里面的第i个。
在累加完前缀和之后答案减去i-1,因为相同大小就不算逆序对了;
【代码】
#include <cstdio>
#include <algorithm> struct data2
{
int d, pos;
}; int n;
__int64 tree_arr[100001] = { 0 };
__int64 ans = 0;
data2 a[100001]; int lowbit(int x) //求整数x的二进制的最靠近右边的数字1所代表的数字。
{
return x & -x; //-x是在x的二进制按位取反之后再加上1的结果。然后和x取与运算。
} int cmp(const data2 &a, const data2 &b)//比较函数。
{
if (a.d > b.d)//按数字从大到小排序。
return 1;
if (a.d == b.d && a.pos < b.pos)//如果数字的大小相同,则靠后的在后面。
return 1;
return 0;
} void find(int now) //一直往左累加长条(区间和)
{
if (now <= 0)//越界了则退出
return;
ans += tree_arr[now];//累加这一段的区间和
find(now - lowbit(now));//一直往左
} void add(int now)//把数组中now位置上的数字递增1
{
if (now > n)
return;
tree_arr[now] ++;
add(now + lowbit(now));//然后继续往左,去递增那些会受到影响的区间。
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
//freopen("F:\\rush_out.txt", "w", stdout);
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i].d); //输入n个数据,并且记录它们原来的位置。
a[i].pos = i;
}
std::sort(a + 1, a + 1 + n, cmp);//把a数组以数字大小为关键字从大到小排序。
int now = 0;
for (int i = 1; i <= n; i++)//把每一个数字放到树状数组中。
{
if (i != 1 && a[i - 1].d == a[i].d)//如果出现了连续相同的数字就记录这是连续相同数字里的第x个,now=x-1;
now++;
else
now = 0;
find(a[i].pos);//往左累加前缀和
ans -= now;//减去重复的
add(a[i].pos);//修改与其相关的区间。
}
printf("%I64d", ans);
return 0;
}
【a703】求逆序对(树状数组的解法)的更多相关文章
- 求逆序对[树状数组] jdoj
求逆序对 题目大意:给你一个序列,求逆序对个数. 注释:n<=$10^5$. 此题显然可以跑暴力.想枚举1到n,再求在i的后缀中有多少比i小的,统计答案即可.这显然是$n^2$的.这...显然过 ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- Bzoj 2141: 排队 分块,逆序对,树状数组
2141: 排队 Time Limit: 4 Sec Memory Limit: 259 MBSubmit: 1310 Solved: 517[Submit][Status][Discuss] D ...
- luogu1908 逆序对 树状数组
题目大意:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对.求一段序列的逆序对数. 对于一个数组T,其一个点的值为值与该点下标相等的A序列中点的个数.对T维护一个树状数 ...
- P1908 逆序对——树状数组&离散化&快读快写の学习
题目简述: 对于给定的一段正整数序列,逆序对就是序列中 a_i>a_jai>aj 且 i<ji<j 的有序对. 输出序列中逆序对的数目. 知识补充: 树状数组: 这东西就是 ...
- 洛谷 P1908 逆序对(树状数组解法)
归并排序解法:https://www.cnblogs.com/lipeiyi520/p/10356882.html 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不 ...
- BZOJ - 3295 动态逆序对 (树状数组套treap)
题目链接 思路和bzoj2141差不多,不过这道题的数据更强一些,线段树套treapT了,树状数组套treap卡过~~ #include<bits/stdc++.h> using name ...
- luogu P1908 逆序对 |树状数组
题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为"逆序对"的 ...
- ACM学习历程—HDU5592 ZYB's Premutation(逆序数 && 树状数组 && 二分)(BestCoder Round #65 1003)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5592 题目大意就是给了每个[1, i]区间逆序对的个数,要求复原原序列. 比赛的时候2B了一发. 首先 ...
随机推荐
- 【hdu 1533】Going Home
[链接]http://acm.hdu.edu.cn/showproblem.php?pid=1533 [题意] 一个N*M地图上有相同数量的字符H和字符m,m代表一个 人,H代表一个房子.人到房子的花 ...
- iOS多语言(国际化)开发(尾随系统 + APP内手动设置)
一:尾随系统切换语言 1>创建好项目project后, 新建一个多语言文件: 2>加入要设置的语言类型: 3>加入成功 细心的朋友可能会发如今English后面写的是3 Files ...
- 对象的序列化与反序列化---IO学习笔记(四)
对象的序列化,反序列化 对象的序列化: 就是将Object转换成byte序列 对象的反序列化: 将byte序列转换成Object 序列化流.反序列化流 序列化流(ObjectOutputStream) ...
- 【C语言】编写函数实现库函数atoi,把字符串转换成整形
//编写函数实现库函数atoi.把字符串转换成整形 #include <stdio.h> #include <string.h> int my_atoi(const char ...
- 动态规划例子:Maximal Square
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...
- 小贝_redis web管理界面工具安装
RedisWEB管理界面工具安装 一.概述 二.文件下载 三.安装过程 一.概述 1.因为redis是基于C/S的方式开发.也就是说,仅仅要满足于redis的client通信要求的,都能够作为redi ...
- Zookeeper源码用ant进行编译为eclipse工程--转载
原文地址:http://www.it165.net/os/html/201411/10142.html Zookeeper GitHub的下载地址是:https://github.com/apache ...
- HDU 5237 Base64
Base64 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Sub ...
- ajax日期參数格式问题
今天遇到ajax传输日期參数后台无法识别的问题,错误异常例如以下. 从异常中能够看出传输到后台的日期数据格式为Thu Aug 13 2015 19:45:20 GMT+0800 (中国标准时间),这样 ...
- MongoDbHelper 帮助类(上)
在网上搜索mongodbHelper的帮助类时,出来的东西都大同小异,再此摘录一下. 这些代码也看了一遍,总是感觉重复的代码太多了,在后续的文章中又整合了一下,请看下篇,欢迎指正! using Sys ...