zoukankan      html  css  js  c++  java
  • BZOJ3295:[CQOI2011]动态逆序对(CDQ分治)

    Description

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数

    Input

    输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
    以下n行每行包含一个1到n之间的正整数,即初始排列。
    以下m行每行一个正整数,依次为每次删除的元素。
    N<=100000 M<=50000

    Output

    输出包含m行,依次为删除每个元素之前,逆序对的个数。

    Sample Input

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    Sample Output

    5
    2
    2
    1

    Solution

    给每个被删除的元素打一个删除时间$t$,设下标为$x$,权值为$y$,那么删除一个元素后,减少的逆序对个数为:

    1、$t$比它大,$x$比它小,$y$比它大。

    2、$t$比它大,$x$比它大,$y$比它小。

    $CDQ$统计一下就好了……

    读错题把删除元素看成删除下标真的智障。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define N (100009)
     6 #define LL long long
     7 using namespace std;
     8 
     9 struct Que
    10 {
    11     int x,y,t;
    12     bool operator < (const Que &a) const
    13     {
    14         return t>a.t;
    15     }
    16 }a[N],tmp[N];
    17 
    18 int n,m,c[N],q[N],ans[N],pos[N];
    19 LL sum;
    20 
    21 inline int read()
    22 {
    23     int x=0,w=1; char c=getchar();
    24     while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();}
    25     while (c>='0' && c<='9') x=x*10+c-'0', c=getchar();
    26     return x*w;
    27 }
    28 
    29 void Update(int x,int k)
    30 {
    31     for (; x<=n; x+=(x&-x)) c[x]+=k;
    32 }
    33 
    34 int Query(int x)
    35 {
    36     int ans=0;
    37     for (; x; x-=(x&-x)) ans+=c[x];
    38     return ans;
    39 }
    40 
    41 void CDQ1(int l,int r)
    42 {
    43     if (l==r) return;
    44     int mid=(l+r)>>1;
    45     CDQ1(l,mid); CDQ1(mid+1,r);
    46     int i=l,j=mid+1,k=l-1;
    47     while (i<=mid || j<=r)
    48         if (j>r || i<=mid && a[i].x<a[j].x)
    49         {
    50             Update(a[i].y,1);
    51             tmp[++k]=a[i]; ++i;
    52         }
    53         else
    54         {
    55             ans[a[j].y]+=Query(n)-Query(a[j].y);
    56             tmp[++k]=a[j]; ++j;
    57         }
    58     for (int i=l; i<=mid; ++i) Update(a[i].y,-1);
    59     for (int i=l; i<=r; ++i) a[i]=tmp[i];
    60 }
    61 
    62 void CDQ2(int l,int r)
    63 {
    64     if (l==r) return;
    65     int mid=(l+r)>>1;
    66     CDQ2(l,mid); CDQ2(mid+1,r);
    67     int i=l,j=mid+1,k=l-1;
    68     while (i<=mid || j<=r)
    69         if (j>r || i<=mid && a[i].x>a[j].x)
    70         {
    71             Update(a[i].y,1);
    72             tmp[++k]=a[i]; ++i;
    73         }
    74         else
    75         {
    76             ans[a[j].y]+=Query(a[j].y-1);
    77             tmp[++k]=a[j]; ++j;
    78         }
    79     for (int i=l; i<=mid; ++i) Update(a[i].y,-1);
    80     for (int i=l; i<=r; ++i) a[i]=tmp[i];
    81 }
    82 
    83 int main()
    84 {
    85     n=read(); m=read();
    86     for (int i=1; i<=n; ++i) a[i].x=i, a[i].y=read(), pos[a[i].y]=i;
    87     for (int i=1; i<=m; ++i) a[pos[q[i]=read()]].t=i;
    88     for (int i=1; i<=n; ++i) if (!a[i].t) a[i].t=m+1;
    89     
    90     for (int i=1; i<=n; ++i) sum+=Query(n)-Query(a[i].y), Update(a[i].y,1);
    91     for (int i=1; i<=n; ++i) Update(a[i].y,-1);
    92     sort(a+1,a+n+1); CDQ1(1,n);
    93     sort(a+1,a+n+1); CDQ2(1,n);
    94     
    95     for (int i=1; i<=m; ++i) printf("%lld
    ",sum), sum-=ans[q[i]];
    96 }
  • 相关阅读:
    MM1排队系统
    java基本概念
    将博客搬至CSDN
    数据库知识点1
    离散分布
    概率论1--基本概念
    一道经典JS题(关于this)
    ajax请求过程中下载文件在火狐下的兼容问题
    熟悉css/css3颜色属性
    打字机游戏Ⅱ之手速pk
  • 原文地址:https://www.cnblogs.com/refun/p/10481145.html
Copyright © 2011-2022 走看看