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 }
posted @ 2012-10-04 10:56  proverbs  阅读(320)  评论(0编辑  收藏  举报