树状数组:求有数多少在a前面的数比a小的思路
Posted wzx-rs-sthn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组:求有数多少在a前面的数比a小的思路相关的知识,希望对你有一定的参考价值。
求比a小在a前面数数量和比a小在a后面数数量的思路:
在看之前,你必须了解树状数组的基本函数
inline ll lowbit(ll x) { return x&(-x); } inline void insert(ll x,ll y)//加入 { while(x<=n) { sum[x]+=y; x+=lowbit(x); } } inline ll findout(ll x)//查找 { ll ans=0; while(x) { ans+=sum[x]; x-=lowbit(x); } return ans; } inline ll cmp(oh a,oh b)//排序 { if(a.v==b.v) return a.num<b.num; else return a.v<b.v; }
求有多少在a前面的数比a小
首先,假如求有多少在a前面的数比a小;
举例: 1 4 2 3 5
然后有5个空位置, _ _ _ _ _ 为sum[5]
第一步 求出sum[1]前缀,答案是0;
插入1, 1 _ _ _ _
第二步 求出sum[4]前缀,答案是1;
插入4, 1 _ _ 4 _
第二步 求出sum[2]前缀,答案是1;
插入4, 1 2 _ 4 _
..........................
这样不断进行下去sum[i]就是 有多少在i前面的数比a小;
所以就转化成了求前缀和的题目了,自然就想到树状数组了;
但是输入的几个数可能会非常大,那么sum数组的下标就会爆;
我们只需知道每个数的大小关系,并不需要知道具体值,所以在处理之前可以离散化;
//离散化 for(ll i=1;i<=n;i++) { a[i].v=read(); a[i].num=i;//将每一个数的位置记下 } sort(a+1,a+n+1,cmp);//从小到大排序, //这样每个数都有顺序了,并且每个数对应的位置没有改变 for(ll i=1;i<=n;i++) b[a[i].num]=i;//把第i小的数位置上赋值为i
具体怎么实现,读者自行手动模拟;
按上面查找的思路
for(ll i=1;i<=n;i++) { ll x=findout(b[i]); ans[i]=x;//先求值,再插入,不然会把自己也算进去的 insert(b[i],1); }
那么求比a小在a后面数数量
则反之
for(ll i=n;i>=1;i--) { ll x=findout(b[i]); ans[i]=x;//反之 insert(b[i],1); }
这样就ok了
以上是关于树状数组:求有数多少在a前面的数比a小的思路的主要内容,如果未能解决你的问题,请参考以下文章