题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

题解

我们发现一个数的贡献,就是就是t'<t(删除时间),xb'<xb(下标),w'>w(权值)的数的数量和t'>t,xb'>xb,w'<w的数的数量之和。

这就是一个三维偏序类型的题,所以做两遍CDQ分治分别的到这两种贡献。最后用总逆序对数减去就好了。

1A真开心。。。

 #include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const long long N=;
long long n,m,a[N],b[N],tmp,tr[N],ans[N],book[N],ma[N],tot;
struct query{
long long id,xb,w;
}q[N],c[N];
bool cmp(query a,query b){
return a.id>b.id;
}
void gb(long long l,long long r){
if(l==r)return;
long long mid=(l+r)>>;
gb(l,mid);
gb(mid+,r);
long long ll=l;
long long lr=mid+;
long long cnt=;
while(ll<=mid&&lr<=r){
cnt++;
if(a[ll]<a[lr]){
b[cnt]=a[ll++];
}
else{
b[cnt]=a[lr++];
tmp+=mid-ll+;
}
}
while(ll<=mid)b[++cnt]=a[ll++];
while(lr<=r)b[++cnt]=a[lr++];
for(long long i=l;i<=r;i++){
a[i]=b[i-l+];
}
}
long long lowbit(long long x){
return x&-x;
}
void add(long long x,long long w){
for(long long i=x;i<=n;i+=lowbit(i)){
tr[i]+=w;
}
}
long long getsum(long long x){
long long ans=;
for(long long i=x;i>=;i-=lowbit(i)){
ans+=tr[i];
}
return ans;
}
void cdq(long long l,long long r){
if(l==r)return;
long long mid=(l+r)>>;
cdq(l,mid);cdq(mid+,r);
long long ll=l;long long rl=mid+;long long now=;
while(ll<=mid&&rl<=r){
if(q[ll].xb<q[rl].xb){
add(q[ll].w,);
c[++now]=q[ll++];
}
else{
ans[q[rl].id]+=getsum(n)-getsum(q[rl].w);
c[++now]=q[rl++];
}
}
while(ll<=mid){
add(q[ll].w,);
c[++now]=q[ll++];
}
while(rl<=r){
ans[q[rl].id]+=getsum(n)-getsum(q[rl].w);
c[++now]=q[rl++];
}
for(long long i=l;i<=mid;i++)add(q[i].w,-);
for(long long i=l;i<=r;i++)q[i]=c[i-l+];
}
void CDQ(long long l,long long r){
if(l==r)return;
long long mid=(l+r)>>;
CDQ(l,mid);CDQ(mid+,r);
long long ll=l;long long rl=mid+;long long now=;
while(ll<=mid&&rl<=r){
if(q[ll].xb>q[rl].xb){
add(q[ll].w,);
c[++now]=q[ll++];
}
else{
ans[q[rl].id]+=getsum(q[rl].w);
c[++now]=q[rl++];
}
}
while(ll<=mid){
add(q[ll].w,);
c[++now]=q[ll++];
}
while(rl<=r){
ans[q[rl].id]+=getsum(q[rl].w);
c[++now]=q[rl++];
}
for(long long i=l;i<=mid;i++)add(q[i].w,-);
for(long long i=l;i<=r;i++)q[i]=c[i-l+];
}
int main(){
scanf("%lld%lld",&n,&m);
for(long long i=;i<=n;i++){
scanf("%lld",&a[i]);
ma[a[i]]=i;
}
for(long long i=;i<=m;i++){
long long x;
scanf("%lld",&x);
q[i].id=i;q[i].xb=ma[x];q[i].w=x;
book[ma[x]]=;
}
tot=m;
for(long long i=;i<=n;i++){
if(book[i]==){
q[++tot].id=m+;q[tot].xb=i;q[tot].w=a[i];
}
}
sort(q+,q+n+,cmp);
cdq(,n);
sort(q+,q+n+,cmp);
CDQ(,n);
gb(,n);
for(long long i=;i<=m;i++){
printf("%lld\n",tmp);
tmp-=ans[i];
}
return ;
}

luogu P3157 [CQOI2011]动态逆序对(CDQ分治)的更多相关文章

  1. LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)

    传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...

  2. 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治

    题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...

  3. P3157 [CQOI2011]动态逆序对 CDQ分治

    一道CDQ分治模板题简单来说,这道题是三维数点对于离线的二维数点,我们再熟悉不过:利用坐标的单调递增性,先按更坐标排序,再按纵坐标排序更新和查询时都直接调用纵坐标.实际上,我们是通过排序将二维中的一维 ...

  4. P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)

    P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...

  5. [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...

  6. 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治

    [BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...

  7. bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)

    3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...

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

    题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 1 ...

  9. [Luogu P3157][CQOI2011]动态逆序对 (树套树)

    题面 传送门:[CQOI2011]动态逆序对 Solution 一开始我看到pty巨神写这套题的时候,第一眼还以为是个SB题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...

随机推荐

  1. JavaScript学习记录一

    title: JavaScript学习记录一 toc: true date: 2018-09-11 18:26:52 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

  2. spm总体说明

    目录 1.如何工作 2.何时使用 1.如何工作 sql plan baseline 是一个关联sql 语句的对象,设计会影响查询优化器生成执行计划,更具体的说,一个sql baseline包含其中的一 ...

  3. WPF学习(一) - XAML

    Window.Grid.TextBox.Button等,都叫元素 xaml文档中,<>用来定义标签,标签可以用来描述元素或元素的属性,如: <Window> <Windo ...

  4. Android 度量单位

    单位 注释 px(像素) 每个像素对应手机上的一个点,在不同设备上1px表示的长度不一定相同 screen size(屏幕尺寸) 指手机对角线的长度,如4.7英寸 resolution(分辨率) 指屏 ...

  5. Android 数据存取

    Android提供了Preference(配置),File(文件),SQLite数据和网络几种数据存取方式 SharedPreference提供了一种轻量级的数据存取方法,应用场合主要是比较少的配置信 ...

  6. Hibernate框架学习(二)——api详解

    一.Configuration对象 功能:配置加载类,用于加载主配置,orm元数据加载. //1.创建,调用空参构造(还没有读配置文件) Configuration conf=new Configur ...

  7. PHP mysql_fetch_array得不到数据

    好久没写PHP了...为了数据库课设开始了PHP速成之旅... 光是简单的注册功能就坑了我好几个小时,不过万事开头难嘛...之后应该会快起来的. 先说一下昨天遇到的小坑, 我的表单是这么写的 < ...

  8. Maven配置文件中配置指定JDK版本

    1. 在setting.xml文件中的<profiles>标签加入如下配置: <profile> <id>jdk-1.8</id> <activa ...

  9. 修改input标签中的placeholder样式

    input::-webkit-input-placeholder { color: #fff !important; } input:-moz-placeholder { color: #fff !i ...

  10. B. Recursive Queries 打表

    Code: #include<cstdio> #include<iostream> #include<algorithm> #include<cstring& ...