zoukankan      html  css  js  c++  java
  • [BZOJ3295][Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 5276  Solved: 1783
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    5 4
    1
    5
    3
    4
    2
    5
    1
    4
    2

    Sample Output

    5
    2
    2
    1

    样例解释
    (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

    HINT

    N<=100000 M<=50000

    cdq分治裸题。

    首先我们把删除改为倒序插入,对于每一个操作,我们记录三元组(x,y,z)表示位置为x数值为y操作时间为z。此时,我们要求对于每一个(x,y,z)的z0<z&&x0<x&&y0》y。

    我们首先考虑对于z从小到大排序,这样,我们就能忽略z的影响。此时,我们要求x0<x&&y0>y的组数。

    现在我们开始分治。

    首先对于区间(l,r),区间(l,mid)中所有元素的z都小于(mid+1,r)中所有元素的z,所以我们考虑(l,mid)中的修改对(mid+1,r)中的每个元素的影响。

    现在我们对区间(l,mid)中的所有元素打上标记,使其成为修改操作,对于区间(mid+1,r)中的所有元素打上标记,使其成为询问操作。

    我们对区间(l,r)以x为第一关键字排序,这样,我们要求的就是a[i].y<a[j].y(i>j) a[i].y>a[j].y(i<j)的个数,可以用树状数组维护。

    处理完区间(l,r),我们可以分治处理(l,mid)(mid+1,r)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cmath>
     6 #include<algorithm>
     7 using namespace std;
     8 int n,m;
     9 struct data
    10 {
    11     int x,y,z;
    12     int flag;
    13 }a[100008],b[100008];
    14 int w[100008];
    15 bool cmp1(data s1,data s2){return s1.z<s2.z;}
    16 bool cmp2(data s1,data s2){return s1.x<s2.x;}
    17 int tre[100008];
    18 long long ans[100008];
    19 int lowbit(int x){return x&(-x);}
    20 void update(int x,int ad){for(int i=x;i<=n;i+=lowbit(i)) tre[i]+=ad;}
    21 int query(int x)
    22 {
    23     int re=0;
    24     for(int i=x;i>0;i-=lowbit(i)) re+=tre[i];
    25     return re;
    26 }
    27 void cdq(int l,int r)
    28 {
    29     if(l>=r) return;
    30     int mid=(l+r)>>1;
    31     int cnt=0;
    32     for(int i=l;i<=r;i++)
    33     {
    34         if(i<=mid){b[++cnt]=a[i];b[cnt].flag=0;}
    35         else {b[++cnt]=a[i];b[cnt].flag=1;}
    36     }
    37     sort(b+1,b+cnt+1,cmp2);
    38     for(int i=1;i<=cnt;i++)
    39     {
    40         if(!b[i].flag) update(b[i].y,1);
    41         else ans[b[i].z]+=(long long)(query(n)-query(b[i].y));
    42     }
    43     for(int i=1;i<=cnt;i++) if(!b[i].flag) update(b[i].y,-1);
    44     for(int i=cnt;i>=1;i--)
    45     {
    46         if(!b[i].flag) update(b[i].y,1);
    47         else ans[b[i].z]+=(long long)query(b[i].y);
    48     }
    49     for(int i=1;i<=cnt;i++) if(!b[i].flag) update(b[i].y,-1);
    50     cdq(l,mid); cdq(mid+1,r);
    51 }
    52 int main()
    53 {
    54     scanf("%d%d",&n,&m);
    55     int c=n;
    56     for(int i=1;i<=n;i++)
    57     {
    58         a[i].x=i;scanf("%d",&a[i].y);w[a[i].y]=i;
    59     }
    60     for(int i=1;i<=m;i++)
    61     {
    62         int t;
    63         scanf("%d",&t);
    64         a[w[t]].z=c--;
    65     }
    66     for(int i=n;i>=1;i--) if(!a[i].z) a[i].z=c--;
    67     sort(a+1,a+n+1,cmp1);
    68     cdq(1,n);
    69     for(int i=1;i<=n;i++) ans[i]+=ans[i-1];
    70     for(int i=n;i>=n-m+1;i--) printf("%lld
    ",ans[i]);
    71 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    __attribute__((noreturn))的用法
    selenium定位元素的方法
    zzz
    go语言的第一个helloworld
    mac eclipse 创建Java 工程
    Jmeter:图形界面压力测试工具
    使用 HAProxy, PHP, Redis 和 MySQL 轻松构建每周上亿请求Web站点
    从Log4j迁移到LogBack的理由
    SLF4J和Logback日志框架详解
    security with restful
  • 原文地址:https://www.cnblogs.com/wls001/p/7388663.html
Copyright © 2011-2022 走看看