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 }

      如有错误,欢迎指正。

  • 相关阅读:
    nginx配置反向代理
    hyperchain HVM使用java编写智能合约的编译、部署流程
    leetcode 140单词拆分Ⅱ
    bomblab phase5
    bomb lab 二三阶段
    2021暑假算法学习笔记(基础复习)#2
    2021暑假算法学习笔记(基础复习)#1
    O(logn)最长上升子序列并输出
    A Daily Topic # 7 阶乘的和(二进制/枚举)
    A Daily Topic # 6 星期几(模拟)
  • 原文地址:https://www.cnblogs.com/_inx/p/7236384.html
Copyright © 2011-2022 走看看