zoukankan      html  css  js  c++  java
  • TYVJ 1744 逆序对数(加强版)

    思路:

    与a有关的逆序对数=(在a之前出现的比a大的数+在a之后出现的比a小的数)/2

    当我们删除a时,减少的是 与a有关的逆序对数,当我们把a的位置填充b时增加的是 与b有关的逆序对数,可以用树状数组求

    这样我们相处了nmlogK的算法,显然是不能承受的(K=500000)

    但是我们发现当a相同时我们可以将所有的b在logn的时间内算出来,这样复杂度就成了(m+n)logK了

    完全可以承受~

    PS:不知道为什么我和别人用一样的思路我的代码怎么比他们快3倍啊。。求解释。。(卖萌。。。。)

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 
      6 #define N 500010
      7 
      8 using namespace std;
      9 
     10 struct P
     11 {
     12     int a,b,id;
     13 }p[N];
     14 
     15 int c[N],n,m,a[N],fw[N],inc[N];
     16 __int64 ans[N],anssum;
     17 
     18 inline bool cmp(const P &x,const P &y)
     19 {
     20     return x.a<y.a;
     21 }
     22 
     23 inline int lowbit(int x)
     24 {
     25     return x&-x;
     26 }
     27 
     28 inline int getsum(int x)
     29 {
     30     int rt=0;
     31     while(x)
     32     {
     33         rt+=c[x];
     34         x-=lowbit(x);
     35     }
     36     return rt;
     37 }
     38 
     39 inline void updata(int x,int dt)
     40 {
     41     while(x<N)
     42     {
     43         c[x]+=dt;
     44         x+=lowbit(x);
     45     }
     46 }
     47 
     48 void read()
     49 {
     50     scanf("%d%d",&n,&m);
     51     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
     52     
     53     for(int i=1;i<=n;i++)
     54     {
     55         fw[i]=i-1-getsum(a[i]);
     56         updata(a[i],1);
     57     }
     58     memset(c,0,sizeof c);
     59     
     60     for(int i=n;i>=1;i--)
     61     {
     62         fw[i]+=getsum(a[i]-1);
     63         updata(a[i],1);
     64         anssum+=fw[i];
     65     }
     66     memset(c,0,sizeof c);
     67     
     68     for(int i=1;i<=m;i++)
     69     {
     70         scanf("%d%d",&p[i].a,&p[i].b);
     71         p[i].id=i;
     72     }
     73     
     74     sort(p+1,p+1+m,cmp);
     75 }
     76 
     77 void go()
     78 {
     79     int sp=1;
     80     for(int i=1;i<=n;i++)
     81     {
     82         while(p[sp].a==i)
     83         {
     84             inc[p[sp].id]=i-1-getsum(p[sp].b);
     85             sp++;
     86         }
     87         updata(a[i],1);
     88     }
     89     memset(c,0,sizeof c);
     90     
     91     sp=m;
     92     for(int i=n;i>=1;i--)
     93     {
     94         while(p[sp].a==i)
     95         {
     96             inc[p[sp].id]+=getsum(p[sp].b-1);
     97             sp--;
     98         }
     99         updata(a[i],1);
    100     }
    101     anssum/=2;
    102     for(int i=1;i<=m;i++)
    103         ans[p[i].id]=anssum-fw[p[i].a]+inc[p[i].id];
    104     printf("%I64d\n",anssum);
    105     for(int i=1;i<=m;i++)
    106         printf("%I64d\n",ans[i]);
    107 }
    108 
    109 int main()
    110 {
    111     read();
    112     go();
    113     //system("pause");
    114     return 0;
    115 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    WP8.1 UI 编程 四、图形
    分治法 全排列问题的一个Java实现
    合并排序算法时间复杂度分析
    js如何实现复制粘贴功能
    关于<meta name="applicable-device"content="pc">
    ready
    css文字强制大写输入
    关于input,button标签在苹果手机上显示阴影解决办法
    【C#】中用if判断值是否是否为空
    视频格式MP4,需要转码
  • 原文地址:https://www.cnblogs.com/proverbs/p/2711334.html
Copyright © 2011-2022 走看看