P1908 逆序对

传送门

  这题似乎不应该出现在这里。。

日常做法(归并):

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define maxn 2000003
typedef long long LL;
LL n,ans=0;
LL a[maxn],r[maxn];
inline LL read()
{
    LL kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
void msort(LL s,LL t)
{
    if(s==t) return ;
    LL mid=(s+t)/2;
    msort(s,mid);
    msort(mid+1,t);
    LL i=s,j=mid+1,k=s;
    while(i<=mid&&j<=t)
    {
        if(a[i]<=a[j])
            r[k]=a[i],k++,i++;
        else
        {
            r[k]=a[j],k++,j++;
            ans+=mid-i+1;
        }
    }
    while(i<=mid)
        r[k]=a[i],k++,i++;
    while(j<=t)
        r[k]=a[j],k++,j++;
    for(LL i=s;i<=t;i++)
        a[i]=r[i];
}
int main()
{
    n=read();
    for(LL i=1;i<=n;i++) 
        a[i]=read();
    msort(1,n);
    printf("%lld\n",ans);
    return 0;
}

权值线段树做法:

  需要先预处理,得到每个值在权值线段树中的位置;再按顺序将数字 a[ i ] 插入到树中相应的位置 ,接着询问树中比它大的元素个数,容易知道这些数都与当前的数 a[ i ] 形成逆序对,直接累加进 ans。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define maxn 500002
typedef long long LL;
LL n,ans=0;
LL a[maxn];
struct hh
{ 
    LL l_son,r_son,root;
}sum[maxn<<2];
inline LL read()
{
    LL kr=1,xs=0;
    char ls;
    ls=getchar();
    while(!isdigit(ls))
    {
        if(!(ls^45))
            kr=-1;
        ls=getchar();
    }
    while(isdigit(ls))
    {
        xs=(xs<<1)+(xs<<3)+(ls^48);
        ls=getchar();
    }
    return xs*kr;
}
inline void build_sum(LL k,LL l,LL r)
{
    sum[k].l_son=l;sum[k].r_son=r;
    if(l==r) return ;
    LL mid=sum[k].l_son+sum[k].r_son>>1;
    build_sum(k<<1,l,mid);
    build_sum(k<<1|1,mid+1,r);
}
inline void up_date(LL k,LL q)
{
    if(q==sum[k].l_son&&q==sum[k].r_son)
    {
        sum[k].root++;
        return;
    }
    LL mid=sum[k].l_son+sum[k].r_son>>1;
    if(q<=mid) up_date(k<<1,q) ;
    else if(mid<q) up_date(k<<1|1,q);
    sum[k].root=sum[k<<1].root+sum[k<<1|1].root;
}
inline LL query(LL k,LL r,LL l)
{
    if(r<=sum[k].l_son&&l>=sum[k].r_son ) 
        return sum[k].root ;
    LL mid=(sum[k].l_son+sum[k].r_son)>>1;
    if (r>mid) return query(k<<1|1,r,l);
    else if(l<=mid) return query(k<<1,r,l);
    return query(k<<1,r,mid)+query(k<<1|1,mid+1,l);
}
int main()
{
    n=read();
    for(LL i=1;i<=n;i++)
        a[i]=read();
    build_sum(1,1,n);
    for(LL i=1;i<=n;i++)
    {
        LL tmp=a[i];
        up_date (1,tmp);
        ans+=i-query(1,1,tmp);
    }
    printf("%lld\n",ans);
return 0;
}

 

posted @ 2018-10-17 22:13  落笔映惆怅丶  阅读(221)  评论(0编辑  收藏  举报