Description

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

Input

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

Output

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

HINT

$n \leq 100000$   $m \leq 50000$

  这道题做法很多……但是我来做这道题只是为了练CDQ分治的……

  首先,我们可以考虑当删除一个数之后逆序对数减少了多少。不难发现,减少的逆序对数就是 这个数 前面比它大的数的个数 加上 后面比它小的数的个数。

  那么,如果我们强行把最后数列中剩下的数也删掉,那么我们就得到了$n$个操作,用 $(x_i,y_i,z_i)$ 表示操作$i$是在时刻$z$把$y$位置上值为$x$的数给删掉。

  于是,对于一个操作$i$,这个操作减少的逆序对数为 $x_j>x_i,y_j<y_i,z_j>z_i$以及$x_j<x_i,y_j>y_i,z_j>z_i$的$j$的个数。

  其实这就是一个三维偏序。对于两个式子分别在CDQ分治的时候扫一遍即可。 大概的思路就是排序一维,分治时归并一维,剩下一维再用树状数组来维护。

  下面贴代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010 using namespace std;
typedef long long llg; struct data{
int x,y,b;
bool operator < (const data &h)const{return x>h.x;}
}s[maxn],ss[maxn];
int c[maxn],n,m,a[maxn],ans[maxn];
bool w[maxn]; llg ana; int getint(){
int w=;bool q=;
char c=getchar();
while((c>''||c<'')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=;
while(c>=''&&c<='') w=w*+c-'',c=getchar();
return q?-w:w;
} void add(int x,int y){while(x<=n) c[x]+=y,x+=x&(-x);}
int sum(int x){
int t=;
while(x) t+=c[x],x-=x&(-x);
return t;
} void solve(int l,int r){
if(l>=r) return;
int mid=l+r>>,now=l,kk=l-,k1=l,k2=mid+;
solve(l,mid); solve(mid+,r);
for(int i=mid+;i<=r;i++){
while(s[now].y<s[i].y && now<=mid) add(s[now].b,),now++;
ans[s[i].b]+=sum(n)-sum(s[i].b);
}
for(int i=l;i<now;i++) add(s[i].b,-);
now=r;
for(int i=mid;i>=l;i--){
while(s[now].y>s[i].y && now>mid) add(s[now].b,),now--;
ans[s[i].b]+=sum(n)-sum(s[i].b);
}
for(int i=now+;i<=r;i++) add(s[i].b,-);
while(k1<=mid && k2<=r)
if(s[k1].y<s[k2].y) ss[++kk]=s[k1++];
else ss[++kk]=s[k2++];
while(k1<=mid) ss[++kk]=s[k1++];
while(k2<=r) ss[++kk]=s[k2++];
for(int i=l;i<=r;i++) s[i]=ss[i];
} int main(){
File("a");
n=getint(); m=getint();
for(int i=;i<=n;i++) a[getint()]=i;
for(int i=;i<=m;i++){
s[i].x=getint(); s[i].b=i;
s[i].y=a[s[i].x]; w[s[i].x]=;
}
for(int i=,t=m;i<=n;i++)
if(!w[i]){
s[++t].x=i; s[t].b=t;
s[t].y=a[s[t].x];
}
sort(s+,s+n+); solve(,n);
for(int i=;i<=n;i++) ana+=ans[i];
for(int i=;i<=m;i++){
printf("%lld\n",ana);
ana-=ans[i];
}
}

BZOJ 3295 【Cqoi2011】 动态逆序对的更多相关文章

  1. BZOJ 3295: [Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3865  Solved: 1298[Submit][Sta ...

  2. Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2886  Solved: 924[Submit][Stat ...

  3. bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3295 [题意] n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对. [思路] ...

  4. 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对

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

  5. bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)

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

  6. BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]

    RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...

  7. BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)

    题目大意: 题面传送门 还是一道三维偏序题 每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间 一开始的序列看成n次插入操作 我们先求出不删除时的逆序对总数 ...

  8. BZOJ 3295 [Cqoi2011]动态逆序对 ——CDQ分治

    时间.位置.数字为三个属性. 排序时间,CDQ位置,树状数组处理数字即可. #include <cstdio> #include <cstring> #include < ...

  9. 【BZOJ 3295】动态逆序对 - 分块+树状数组

    题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...

  10. 【Bzoj 3295】 动态逆序对(树套树|CDQ分治)

    [题意] 每次删除一个数,然后问删除前逆序对数. [分析] 没有AC不开心.. 我的树状数组套字母树,应该是爆空间的,空间复杂度O(nlogn^2)啊..哭.. 然后就没有然后了,别人家的树套树是树状 ...

随机推荐

  1. 阿里资深工程师分享支付宝热补丁技术—— AndFix原理

    本文由嵌入式企鹅圈原创团队成员.阿里资深工程师Hao分享. 上次我们介绍了用dexposed方案实施热补丁的原理,它本质上就是hook要修改的函数,这样一来在正式版本发布时就不能直接拿热补丁的代码集成 ...

  2. [Linux 维护]收集centos系统性能指标

    #!/bin/bash # awk 'END{print}' get the last row iplist=$(cat ~/fanr/shell/Weekly/ip.list) for _IP in ...

  3. ibatis动态多条件查询及模糊查询(oracle,mysql,sql)

    首先是模糊查询的问题,开始时我使用如下条件:select * from user where name like '%#value#%'. 可是怎么也不行,好像还报错了.后来在网上找到了解决方法,就是 ...

  4. c# winform插件

    插件接口 namespace IMsg { ///<summary> /// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口 /// 换句话说,主程序只认识插件里的这些方法 /// ...

  5. 使用DBI(perl)实现文本文件的导入导出mysql

    DBI 是perl脚本连接数据库的一个模块.perl脚本相对shell更灵活,功能更强大,跨平台能力强.相对可执行jar包要简单很多. ​1.下载安装包DBI-1.631.tar.gzperl脚本下载 ...

  6. android XML布局 属性与运用

    padding 设置组件四边的间距,如20.0dip

  7. 三:shell运算符

    1:declare命令 shell默认是字符串型        如果需要加减乘除,需要定义为整型declare命令:改变默认变量的类型decalre [+/-] [选项]  变量名      -给变量 ...

  8. ganglia安装简记

    首先需要安装EPEL的源. yum install -y ganglia.x86_64 ganglia-gmetad.x86_64 ganglia-web.x86_64 ganglia-gmond.x ...

  9. Containers Reserved yarn resourcemanager

    yarn rm的管理页面中显示了集群的概况,其中有一个指标叫Containers Reserved . 预留的容器,为什么会预留,集群的资源使用饱合,新的app请求的资源一般会进入pending状态, ...

  10. Hadoop2.6 datanode配置在线更新

    datanode 的配置可以在线更新了,http://blog.cloudera.com/blog/2015/05/new-in-cdh-5-4-how-swapping-of-hdfs-datano ...