树状数组+ 离散化 求逆序数
来源:互联网 发布:网络搜索不到打印机 编辑:程序博客网 时间:2024/05/24 06:39
我们先来看一道题。
poj 2299 http://poj.org/problem?id=2299
这道算是 树状数组 + 离散化 求逆序数的基础。
我们先来了解以下离散化的作用:解决数据范围过大。无法用自身作为数组的下表存放。所以,离散化能够帮助我们有效的解决:当数据只与它们之间的相对大小有关,而与具体是多少无关的问题。
在离散化中用到unique函数:
unique的作用是“去掉”容器中相邻元素的重复元素,它实质上是一个伪去除,它会把重复的元素添加到容器末尾,而返回值是去重之后的尾地址。
//#include<bits/stdc++.h>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 501000#define ll long longint a[N], s[N], sum[N];int n;void update(int x, int y){ while (x <= n){ sum[x] += y; x += x & -x; }}ll read(ll x){ ll ans = 0; while (x){ ans += sum[x]; x -= x & -x; } return ans;}int main (){ while (scanf("%d",&n)!=EOF && n){ memset(sum,0,sizeof(sum)); memset(s,0,sizeof(s)); for (int i = 1; i <= n; i++) scanf("%d",&a[i]), s[i] = a[i]; sort(s+1,s+n+1); ll Ans = 0; int k = unique(s+1, s+n+1) - s; for (int i = 1; i <= n; ++i) a[i] = lower_bound(s+1,s+n+1,a[i]) - s ; for (int i = 1; i <= n; ++i){ ll temp = read(a[i]); Ans += i -temp - 1; update(a[i],1); } printf("%lld\n",Ans); } return 0;}
这道题 完全可以作为 树状数组+ 离散化 求逆序数 的模板。
接下来放一道最近最到的难题。 也正因为如此才会再一次地看下树状数组。
牛客练习赛7 E 珂朵莉的数列
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
珂朵莉给了你一个序列,有个子区间,求出她们各自的逆序对个数,然后加起来输出
输入描述:
第一行一个数 n 表示这个序列 a 的长度
之后一行 n 个数,第i个数表示ai
输出描述:
输出一行一个数表示答案
示例1
输入
10
1 10 8 5 6 2 3 9 4 7
输出
270
示例2
输入
20
6 0 4 5 8 8 0 6 6 1 0 4 6 6 0 0 7 2 0 5
输出
3481
备注:
对于100%的数据,n <=
1000000 ,0 <= 序列中每个数 <= 1000000000
官方题解:
10分做法:puts( “0” );
30分做法:直接暴力
60分做法:优化暴力
70分做法:
考虑计算贡献
如果有i < j , a[i] > a[j]的点对( i , j )
则会在1 <= l <= i , j <= r <= n的子区间[l,r]中出现
则对答案的贡献是i * ( n - j + 1 )
所以用树状数组维护或者分治(归并排序)即可
做法和求普通逆序对差不多
80->100分做法:
发现答案是O( n^4 )级别
冷静分析出题人会不会卡爆long long
发现随机数据答案是O( n^4 )级别
放弃吧,还是写高精度吧
根据常数不等,80分->100分
卡到80% 估计很绝望233,高精度真的太秀了,我的龟龟。
但是这道题可以不用高精度写,在大佬那儿学到了一个的小技巧(●ˇ∀ˇ●)。
如何处理爆long long!
#include<bits/stdc++.h>using namespace std;#define ll long long#define N 1100000ll a[N],b[N],sum[N];ll n;void update(int x, int y){ while (x <= n){ sum[x] += y; x += x & -x; }}ll read (ll x){ ll ans = 0; while (x){ ans += sum[x]; x -= x &-x; } return ans;}int main (){ scanf("%lld",&n); for (int i = 1; i <= n; i++) scanf("%lld",&a[i]), b[i] = a[i]; sort(b+1,b+1+n); int k = unique(b+1,b+1+n) - b; ll ans1 = 0, ans2 = 0; ll mx = 1e18; for (int i = 1; i <= n; i++){ a[i] = lower_bound(b+1,b+1+n,a[i]) - b; ans1 += (ll)(n-i+1) * (read(n) - read(a[i])); if (ans1 >= mx) ans2+= ans1/mx, ans1 %= mx; update(a[i],i); } if (ans2) printf("%lld%018lld\n",ans2,ans1); else printf("%lld\n",ans1); return 0;}
- 离散化+树状数组求逆序数
- 树状数组离散化求逆序数
- 树状数组+ 离散化 求逆序数
- 求逆序数(树状数组+离散)
- HDU5792(离散化+树状数组求逆序数)树状数组求逆序深入讲解
- POJ 2299 离散化+树状数组求逆序数
- POJ 2299 树状数组求逆序数+离散化
- poj 2299 离散化+树状数组求逆序数
- 离散化+树状数组 求逆序数POJ2299
- poj 2299(离散化+树状数组求逆序数)
- nyoj117求逆序数(离散化+树状数组/归并排序)
- poj 2299 树状数组求逆序数+离散化
- nyoj 117 求逆序数 【树状数组】+【离散化】
- Ultra-QuickSort(离散化+树状数组求逆序数)
- 树状数组求逆序数的模板(离散化处理)
- 树状数组+离散化 《求逆序数对》
- 离散化加树状数组求逆序数。
- POJ 2299 <离散化+树状数组求逆序数对>
- Java中的单例
- Keras入门课2 -- 使用CNN识别mnist手写数字
- 5. Longest Palindromic Substring
- HTML DOM Event 对象(Document 对象)
- Eclipse常用功能和详细快捷键
- 树状数组+ 离散化 求逆序数
- 分别用css、JS、jQuery实现二级菜单、三级菜单
- 深度学习: random initialization (随机初始化)
- JAVA学习笔记(二)字符串的比较
- 面向接口编程,调WebServices
- 2017Android项目实践技巧清单
- 点亮流水灯
- JS做选中input全部删除
- [C/C++语言标准] ISO C99/ ISO C11/ ISO C++11/ ISO C++14 Downloads