线段树求逆序数
来源:互联网 发布:淘宝怎么提高宝贝权重 编辑:程序博客网 时间:2024/06/09 18:15
线段树是一类非常有用的数据结构 这个可以体现到求解一组序列的逆序数上来
可以这么想 我们求逆序数的时候,对于每一个数字都找前面比他大的数字的数目
例如 9 5 7 9这三个序列 我们先找5前面比5大的数字的个数 很明显是9 有一个
我们继续找7前面比7大的个数 也是9
找 9 前面比9大的个数 和明显没有
按照这个想法实现的是O(n^2)的一个算法 复杂度不是很好
既然是区间操作 我们想到了线段树
我们先建立一个空树 然后呢 按照这个序列的顺序将每个值插入 ,每次插入伴随一次查询 查询前面插入的比这次插入的大的数字的个数
然后就可以了 复杂度 nlogn 可以接受
需要注意 :1.很多时候可能要离散化 这个很容易想 因为如果数字是long long 类型以及以上的那么空间就爆了
2.注意建立空树的时候要在 1-n+1上建立空树 因为有可能查询n query(1,n+1,n)的时候就出错了 这样并不影响结果,仔细体会一下
下面这是没有离散的代码
#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn = 1e5+10;int arr[maxn];struct node{int sum,l,r;};node segtree[4*maxn];int fa[maxn];void buildtree(int num,int l,int r){ if(l==r) { segtree[num].l=segtree[num].r=l; fa[r]=num; segtree[num].sum=0; return ; } segtree[num].l=l; segtree[num].r=r; segtree[num].sum=0; int mid=(l+r)/2; buildtree(2*num,l,mid); buildtree(2*num+1,mid+1,r);}int query(int num,int l,int r){ if(segtree[num].l==l&&segtree[num].r==r) { return segtree[num].sum; } int mid=(segtree[num].l+segtree[num].r)/2; if(l>mid) { return query(2*num+1,l,r); } else if(r<=mid) { return query(2*num,l,r); } else { return query(2*num,l,mid)+query(2*num+1,mid+1,r); }}void update(int num,int x){ if(segtree[num].l==segtree[num].r) { segtree[num].sum++; return ; } int mid=(segtree[num].l+segtree[num].r)/2; if(x<=mid) update(2*num,x); else update(2*num+1,x); segtree[num].sum++;}int main(){ int n; cin>>n; for(int i=1;i<=n;i++) cin>>arr[i]; buildtree(1,1,n+1); int sum=0; for(int i=1;i<=n;i++) { sum+=query(1,arr[i]+1,n+1); update(1,arr[i]); } cout<<sum<<endl; return 0;}下面是离散化方式 :
#include <stdio.h>#include <iostream>#include <vector>using namespace std;int arr[1000];int save[1000];vector<int> v;int getid(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}int main(){ int n; cin>>n; for(int i=1;i<=n;i++) { cin>>arr[i]; v.push_back(arr[i]); } sort(v.begin(),v.end()),unique(v.begin(),v.end()); for(int i=1;i<=n;i++) save[i]=getid(arr[i]); return 0;}
注意离散化的时候一定要保证用了sort和unique 并且unique要在sort之后才可以用
但是用了stl很容易t所以离散化尽量自己做 下面是进行离散化 线段树求逆序操作
#include <iostream>#include <algorithm>#include <stdio.h>#include <vector>#include <string.h>#include <stdlib.h>#include <math.h>#include <string>#include <ctype.h>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define inf 1e9+7int arr[1100200];int brr[1100200];int hashh[1100200];int save[1100200];int sum[3300200];vector<int> q;int n,m;void update(int num,int l,int r,int x){ if(l==r) {sum[num]++;return;} int mid=(l+r)>>1; if(x<=mid) update(num<<1,l,mid,x); else if(x>mid) update((num<<1)|1,mid+1,r,x); sum[num]++;}int query(int num,int l,int r,int left,int right){ if(l==left&&r==right) return sum[num]; int mid=(l+r)>>1; if(right<=mid) return query(num<<1,l,mid,left,right); else if(left>mid) return query((num<<1)|1,mid+1,r,left,right); else return query(num<<1,l,mid,left,mid)+query((num<<1)|1,mid+1,r,mid+1,right);}int getid(int x) {return lower_bound(save+1,save+m+1,x)-save;}int main(){ while(scanf("%d",&n)!=EOF&&n){ memset(sum,0,sizeof(sum)); for(int i=1;i<=n;i++) { scanf("%d",&arr[i]); hashh[i]=arr[i]; } sort(hashh+1,hashh+n+1); m=1;save[1]=hashh[1]; for(int i=2;i<=n;i++) if(hashh[i]!=hashh[i-1]) save[++m]=hashh[i]; int size=m; for(int i=1;i<=n;i++) brr[i]=getid(arr[i]); long long cnt=0; for(int i=1;i<=n;i++) { update(1,1,size+10,brr[i]); cnt+=(long long)query(1,1,size+10,brr[i]+1,size+10); } cout<<cnt<<endl; } return 0;}
1 0
- 线段树---求逆序数
- 线段树求逆序数
- 线段树--求逆序数
- 归并求逆序数 树状数组求逆序数 线段树求逆序数
- hdu 1394(线段树求逆序数)
- 线段树求逆序数 hdu1394
- HDU1394用线段树求逆序数
- hdu 1394 线段树 求逆序数
- 线段树求逆序数(单点更新)
- poj2299-------------线段树求逆序数
- hdu 1394 线段树求逆序数
- hdu1394 线段树求最小逆序数
- hdu1394(线段树求逆序数)
- 线段树求逆序数hdu1394
- hdu_1394,线段树求逆序数
- hdu 1394 线段树求逆序数
- HDU 1394 线段树求逆序数
- nyoj117 求逆序数【线段树】
- Intellij idea 常用设置
- TCP协议通讯原理
- MeasureSpec
- LeetCode-203:Remove Linked List Elements
- TED :Linux 操作系统之父
- 线段树求逆序数
- Map
- Visual Studio 2015 TeamWork With TFS2015
- java-框架-apache.commons.*工具
- HOJ 1004题 题解
- 在Android Studio中使用shareSDK进行社会化分享(图文教程)
- JAVA 面向对象之深入构造器
- 求出 N 座大楼的外轮廓线
- 每日一省之————二分查找法demo