HDU2689-树状数组&逆序数|分治-Sort it

来源:互联网 发布:棋牌软件开发定制 编辑:程序博客网 时间:2024/05/27 20:09

https://vjudge.net/problem/HDU-2689
给定一个 1-n的全排列,问逆序数是多少。
每次更新,然后统计前面比i小的数。
或者用分治的思想。每次折半判断
逆序数总共分成三种情况
1这里写图片描述

#include <iostream>#include <cstdio>#include <cstring>using namespace std;/* 方法。    判断里面有几个大于i的数.*/const int maxn=2000;int a[maxn];int lowbit(int a){   return a&(-a);}int t;void update(int x,int b){     for(int i=x;i<=t;i+=lowbit(i)){        a[i]++;//单点更新     }}int query(int x){    int sum=0;    for(int i=x;i>0;i-=lowbit(i))        sum+=a[i];//求和return sum;}int main(){    int x;    while(~scanf("%d",&t)){           memset(a,0,sizeof(a));            int all=0;          for(int i=0;i<t;i++){              scanf("%d",&x);               update(x,1);               all+=(i+1-query(x));               //cout<<all<<endl;          }          printf("%d\n",all);    }    return 0;}

分治

#include <bits/stdc++.h>using namespace std;/*或者用分治。这里有一个对分治法的理解,那就是在对子问题排序之后,计算 交叉的情况时,默认子问题已经排序过了,因为其逆序数已经计算。*/typedef long long ll;vector<int>v;long long  solve(int l,int r,vector<int>&a){     int len=a.size();     if(len<=1) return 0;     ll cnt=0;     vector<int>f(a.begin(),a.begin()+len/2);     vector<int>s(len/2+a.begin(),a.end());     cnt+=solve(l,len/2,f);     cnt+=solve(len/2,r,s);     //cout<<cnt<<"!!"<<endl;     int ps=0;     int pf=0;     int zb=0;     while(!(ps==s.size()&&pf==f.size())){          if((ps==s.size()||f[pf]<=s[ps])&&pf<f.size())             {a[zb++]=f[pf++];            //cout<<l<<" "<<r<<f[pf-1]<<endl;            }           else{              cnt+=1ll*(len/2-pf);              a[zb++]=s[ps++];            //cout<<l<<" "<<r<<s[ps-1]<<endl;           }     }     return cnt;}int main(){    int t;      int k;     while(~scanf("%d",&t)){           v.clear();           v.resize(t);           for(int i=0;i<t;i++){               scanf("%d",&k);               v.push_back(k);           }           printf("%lld\n",solve(0,v.size(),v));           //for(int i=0;i<v.size();i++)            //cout<<v[i]<<endl;     }    return 0;}
原创粉丝点击