zoukankan      html  css  js  c++  java
  • 用树状数组处理逆序对[数据结构][树状数组]

    逆序对

    ——!x^n+y^n=z^n

      可以到这里[luogu]:

    https://www.luogu.org/problem/show?pid=1908

    题意:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

      假如为这些数为:

    8 2 3 1 7

      如果我们把数一个个加进来,用一个数组a[i]统计i出现了几次。

    a的初始状态:

     

    8加进来后:

    由于不存在比8大的数,说明没有产生逆序对

    2加进来后:

    统计比2大的数(即产生逆序对),有一个

    3加进来后:

    逆序对+1

    ...

      可能大家都看出来了,即每次加入统计前面的数有几个比自己大,即统计后面的数有几个,这种事情当然用树状数组操作很方便。

      其实如果大家在想一想,如果我把这些数倒过来看,那我们就是要统计前面有几个数比自己小,这不就和树状数组操作一模一样?

      当然在进行上述操作可能就看出问题了,就是4,5,6这些是没用的,这样不仅费时还费空间。

      其实上面的数和

    5 2 3 1 4 的逆序对数是一样的,这样我们的操作就完美了。(当然你要主要有几个数是一样的情况)

    附上Lowbee的代码

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 #define maxn 100010
     7 struct lys{
     8     int pos,v;
     9 }p[maxn];
    10 int bit[maxn],a[maxn];
    11 inline int read();
    12 namespace Liisa{
    13     int n;
    14     int lowbit(int x){
    15         return x&(-x);
    16     }
    17     bool cmp(const lys &a,const lys &b){
    18         return a.v<b.v;
    19     }
    20     //插入,或者理解为单点更新 
    21     void insert(int x){
    22         int i;
    23         for(i=x;i<=n;i+=lowbit(i))
    24             bit[i]++;
    25     }
    26     //统计和 
    27     long long getsum(int x){
    28         int i;
    29         long long res=0;
    30         for(i=x;i>0;i-=lowbit(i))
    31             res+=bit[i];
    32         return res;
    33     }
    34     long long ans=0;
    35     int main(){
    36         n=read();
    37         int i;
    38         for(i=1;i<=n;i++){
    39             p[i].pos=i; p[i].v=read();
    40         }
    41         sort(p+1,p+1+n,cmp);
    42         int s=0;
    43         p[0].v=-1;
    44         //离散化操作 
    45         for(i=1;i<=n;i++){
    46             if(p[i].v!=p[i-1].v) s++;
    47             a[p[i].pos]=s;
    48         }
    49         //计算逆序对,从后往前读 
    50         for(i=n;i>=1;i--){
    51             insert(a[i]);
    52             //统计比自己小的 
    53             ans+=getsum(a[i]-1);
    54         }
    55         cout<<ans<<endl;
    56     }
    57 }
    58 int main(){
    59     Liisa::main();
    60     return 0;
    61 }
    62 inline int read(){
    63     int k=0,f=1;
    64     char c=getchar();
    65     while(c>'9'||c<'0'){
    66         if(c=='-') f=-1;
    67         c=getchar();
    68     }
    69     while(c>='0'&&c<='9'){
    70         k=k*10+c-'0';
    71         c=getchar();
    72     }
    73     return k*f;
    74 }

      如有错误,欢迎指正。

  • 相关阅读:
    8.10
    今日头条笔试题 1~n的每个数,按字典序排完序后,第m个数是什么?
    Gym 100500B Conference Room(最小表示法,哈希)
    CodeForces 438D The Child and Sequence(线段树)
    UVALIVE 6905 Two Yachts(最小费用最大流)
    Gym Conference Room (最小表示法,哈希)
    hdu 2389 Rain on your Parade(二分图HK算法)
    Codeforces Fox And Dinner(最大流)
    zoj 3367 Counterfeit Money(dp)
    ZOJ3370. Radio Waves(2-sat)
  • 原文地址:https://www.cnblogs.com/_inx/p/7236384.html
Copyright © 2011-2022 走看看