zoukankan      html  css  js  c++  java
  • 【分块】bzoj3295 [Cqoi2011]动态逆序对

    考虑每次删除pos位置一个数x后,所造成的的影响就是,逆序对的个数少了在1~pos-1中大于x的数的个数加上pos+1~n中小于x的数的个数。

    那么我们需要的操作就只有查询区间内比某数大(小)的个数。

    ↑,分块经典操作,每个块里维护一个有序表。

    由于有删除,最好每个块用一个vector。

    对于原数列怎么办呢?只需要弄一个vis数组,vis[i]表示i位置的数已经删除即可。(要找到v在原数列中的位置的话,在其所在块暴力即可。)

    查询时对整块二分,对要删的元素所在块分成两段暴力。

    O(n*sqrt(n)*log2(sqrt(n)))

    【觉得我已经丧心病狂了,bzoj的树套树题只会用分块水怎么办啊,一旦不是总时限不就T了吗……QAQ】

    P.S.请用long long。

     1 #include<cstdio>
     2 #include<vector>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 bool vis[100001];
     7 int n,m,a[100001],sum,num[100001],sz,l[400],r[400],v;
     8 long long ans;
     9 vector<int>b[400];
    10 vector<int>::iterator it;
    11 int Res,Num;char C,CH[12];
    12 inline int G()
    13 {
    14     Res=0;C='*'; 
    15     while(C<'0'||C>'9')C=getchar();
    16     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
    17     return Res;
    18 }
    19 inline void P(long long x)
    20 {
    21     Num=0;if(!x){putchar('0');puts("");return;}
    22     while(x>0)CH[++Num]=x%10,x/=10;
    23     while(Num)putchar(CH[Num--]+48);
    24     puts("");
    25 }
    26 void makeblock()
    27 {
    28     sz=sqrt((double)n*log2(n));
    29     for(sum=1;sum*sz<n;sum++)
    30       {
    31         l[sum]=(sum-1)*sz+1;
    32         r[sum]=sum*sz;
    33         for(int i=l[sum];i<=r[sum];i++) num[i]=sum,b[sum].push_back(a[i]);
    34         sort(b[sum].begin(),b[sum].end());
    35       }
    36     l[sum]=sz*(sum-1)+1; r[sum]=n;
    37     for(int i=l[sum];i<=r[sum];i++) {num[i]=sum; b[sum].push_back(a[i]);}
    38     sort(b[sum].begin(),b[sum].end());
    39 }
    40 int D[100001];inline int lowbit(const int &x){return x&(-x);}
    41 inline int getsum(int x){int res=0;while(x>0){res+=D[x];x-=lowbit(x);}return res;}
    42 inline void add(int x,const int &d){while(x<=n){D[x]+=d;x+=lowbit(x);}}
    43 void Get_First_Ans()
    44 {for(int i=1;i<=n;i++){add(a[i],1);ans+=(long long)i-getsum(a[i]);}}
    45 int Get_Pos(const int &v,const int &L,const int &R)
    46 {for(int i=L;i<=R;i++) if(!vis[i] && a[i]==v) return i;}
    47 void update()
    48 {
    49     for(int i=1;i<=sum;i++)
    50       {
    51         it=lower_bound(b[i].begin(),b[i].end(),v);
    52         if(*it==v)
    53           {
    54             int p=Get_Pos(v,l[i],r[i]); vis[p]=true;
    55             for(int j=1;j<i;j++) ans-=(long long)(b[j].end()-upper_bound(b[j].begin(),b[j].end(),v));
    56             for(int j=l[i];j<p;j++) if(!vis[j] && a[j]>v) ans--;
    57             for(int j=i+1;j<=sum;j++) ans-=(long long)(lower_bound(b[j].begin(),b[j].end(),v)-b[j].begin());
    58             for(int j=p+1;j<=r[i];j++) if(!vis[j] && a[j]<v) ans--;
    59             b[i].erase(it);
    60             break;
    61           }
    62       }
    63 }
    64 int main()
    65 {
    66     n=G();m=G();
    67     for(int i=1;i<=n;i++) a[i]=G();
    68     Get_First_Ans();
    69     makeblock();
    70     for(int i=1;i<=m;i++)
    71       {
    72         v=G(); P(ans);
    73         update();
    74       }
    75     return 0;
    76 }
  • 相关阅读:
    剑指Offer对答如流系列
    剑指Offer对答如流系列
    KMP算法
    殊途同归
    从m个数中取top n
    用红黑树实现500万数据的动态排序
    返璞归真
    second blog编程之美------控制cpu曲线
    first blog编程之美-----计算1的个数
    mathematica入门学习记录:
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4029339.html
Copyright © 2011-2022 走看看