openjudge 求逆序对数(线段树+离散化)

来源:互联网 发布:快速提高英语口语 知乎 编辑:程序博客网 时间:2024/06/05 11:20

求逆序对数

  • 查看
  • 提交
  • 统计
  • 提问
总时间限制: 
500ms 
内存限制: 
65536kB
描述

对于一个长度为N的整数序列A,满足i < j 且 Ai > Aj.的数对(i,j)称为整数序列A的一个逆序
<j<=n且ai><j<=n且ai><j<=n且ai><j<=n且ai>

请求出整数序列A的所有逆序对个数

输入
输入包含多组测试数据,每组测试数据有两行
第一行为整数N(1 <= N <= 20000),当输入0时结束
第二行为N个整数,表示长为N的整数序列
输出
每组数据对应一行,输出逆序对的个数
样例输入
51 2 3 4 555 4 3 2 1110
样例输出
0100
tips:没有给明整数范围,也没说整数是否可以为非正。离散化吧
#include<iostream>#include<cstring>#include<utility>#include<vector>#include<cstdio> #include<algorithm>using namespace std;const int maxn=110000;typedef pair<int,int>pr;int sum[maxn<<2];vector<pr>v;void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int rt,int l,int r){if(l==r){sum[rt]=0;return;}int m=(l+r)>>1;build(rt<<1,l,m);build(rt<<1|1,m+1,r);pushup(rt);}void update(int x,int rt,int l,int r){if(l==r){sum[rt]++;return;}int m=(l+r)>>1;if(x<=m)update(x,rt<<1,l,m);else update(x,rt<<1|1,m+1,r);pushup(rt);}int query(int rt,int l,int r,int ll,int rr){if(ll<=l&&rr>=r){return sum[rt];}int ret=0;int m=(l+r)>>1;if(ll<=m)ret+=query(rt<<1,l,m,ll,rr);if(rr>m)ret+=query(rt<<1|1,m+1,r,ll,rr);return ret; }int main(){int n;while(scanf("%d",&n),n){//build(1,1,maxn);memset(sum,0,sizeof(sum));v.clear();for(int i=1;i<=n;i++){int x;scanf("%d",&x);v.push_back(make_pair(x,i));}stable_sort(v.begin(),v.end());int ans=0;for(int i=0;i<v.size();i++){update(v[i].second,1,1,maxn);ans+=query(1,1,maxn,v[i].second+1,maxn);}cout<<ans<<endl;} return 0; } 


阅读全文
0 0
原创粉丝点击