LG1393 动态逆序对
问题描述
题解
本题可以使用\(\mathrm{CDQ}\)分治完成。
二维偏序
根据偏序的定义,逆序对是一个二维偏序,但这个二维偏序比较特殊:
\(i>j,a_i<a_j\)
\(i<j,a_i>a_j\)
以上两种情况都符合这个二维偏序。
三维偏序
但带修改二维偏序怎么做?
我们将删除操作视为插入操作。
则没有没删除的插入时间为\(1\),第\(i\)个被删除的,插入时间为\(m-i+2\)
将插入时间作为第一维,数列位置为第二维,数值为第三维。
做三维偏序即可。
注意由于逆序对的定义,三维偏序仍是两种情况。
\(\mathrm{CDQ}\)分治
简要介绍一下\(\mathrm{CDQ}\)分治。
\(\mathrm{CDQ}\)分治是一种分治算法(废话),是一个叫做陈丹琪的女选手在\(2009\)(记不清了)年提出的。当时提出时是用于优化一类\(\mathrm{DP}\)问题的。后来\(\mathrm{CDQ}\)分治被主要用于解决三维偏序问题。
\(\mathrm{CDQ}\)分治思想类似于归并排序。归并排序每次将区间\([l,r]\)划分为\([l, \lfloor\frac{l+r}{2} \rfloor]\)和\([\lfloor \frac{l+r}{2} \rfloor + 1,r]\)
考虑三维偏序问题模型,\(i\)对\(j\)有贡献需要满足\(a_i<a_j,b_i<b_j,c_i<c_j\)。
\(\mathrm{CDQ}\)分治先将\(a\)升序排序,再进行归并排序,使\(b\)有序。
考虑区间\([l,r]\),当完成左右区间的归并排序后,由于一开始先对\(a\)进行了排序,则\(\forall x \in[l, \lfloor\frac{l+r}{2} \rfloor],\forall y \in [\lfloor \frac{l+r}{2} \rfloor + 1,r]\),一定有\(a_x<a_y\),这时候分别维护左区间和右区间指针,同时用树状数组维护值即可。
具体请见【模板】三维偏序(陌上花开)题解区。
\(\mathrm{code}\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,tmp;
struct node{
int a,b,c,ans;
}a[40007];
int anss[40007];
template<typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
if(ch=='-'){
ch=getchar();fh=-1;
}
else fh=1;
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
x*=fh;
}
struct BIT{
int c[40007];
void change(int p,int k){
while(p<=40000){
c[p]+=k;p+=(p&(-p));
}
}
int query(int p){
int re=0;
while(p){
re+=c[p];p-=(p&(-p));
}
return re;
}
}T;
bool comp(node a,node b){
if(a.a!=b.a) return a.a<b.a;
if(a.b!=b.b) return a.b<b.b;
return a.c<b.c;
}
bool cmp(node a,node b){
if(a.b!=b.b) return a.b<b.b;
return a.c<b.c;
}
bool fuck(node a,node b){
if(a.b!=b.b) return a.b>b.b;
return a.c>b.c;
}
void cdq(int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);cdq(mid+1,r);
sort(a+l,a+mid+1,cmp);sort(a+mid+1,a+r+1,cmp);
int i,j=l,tot=0;
for(i=mid+1;i<=r;i++){
while(j<=mid&&a[j].b<=a[i].b){
T.change(a[j].c,1);++j;++tot;
}
a[i].ans+=tot-T.query(a[i].c);
}
for(i=l;i<j;i++) T.change(a[i].c,-1);
sort(a+l,a+mid+1,fuck);sort(a+mid+1,a+r+1,fuck);
for(i=mid+1,j=l;i<=r;i++){
while(j<=mid&&a[j].b>=a[i].b){
T.change(a[j].c,1);++j;
}
a[i].ans+=T.query(a[i].c);
}
for(i=l;i<j;i++) T.change(a[i].c,-1);
}
bool fake(node a,node b){
return a.c<b.c;
}
void lsh(){
sort(a+1,a+n+1,fake);
for(register int i=1;i<=n;i++) a[i].c=i;
}
signed main(){
read(n);read(m);
for(register int i=1;i<=n;i++){
read(a[i].c);a[i].a=1,a[i].b=i;
}
for(register int i=1;i<=m;i++){
read(tmp);a[tmp].a=m-i+2;
}
lsh();
sort(a+1,a+n+1,comp);
cdq(1,n);
for(register int i=1;i<=n;i++) anss[a[i].a]+=a[i].ans;
for(int i=1;i<=n;i++)anss[i]+=anss[i-1];
for(int i=m+1;i>0;i--)printf("%lld%c",anss[i]," \n"[i==1]);
return 0;
}
LG1393 动态逆序对的更多相关文章
- 【LG1393】动态逆序对
[LG1393]动态逆序对 题面 洛谷 题解 \(CDQ\)分治,按照时间来分治 应为一个删除不能对前面的操作贡献,所以考虑一个删除操作对它后面时间的操作的贡献 用上一个答案减去次贡献即可 代码 #i ...
- BZOJ 3295: [Cqoi2011]动态逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3865 Solved: 1298[Submit][Sta ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- 【Luogu1393】动态逆序对(CDQ分治)
[Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- bzoj3295[Cqoi2011]动态逆序对 树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5987 Solved: 2080[Submit][Sta ...
- cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )
hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
随机推荐
- Acwing40. 顺时针打印矩阵
地址 https://www.acwing.com/solution/acwing/content/3623/ 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 样例 输入: [ [, ...
- (day67)作业
有以下广告数据(实际数据命名可以略做调整) ad_data = { tv: [ {img: 'img/tv/001.png', title: 'tv1'}, {img: 'img/tv/002.png ...
- 【python爬虫】正则表达式
一.数据的分类 1.结构化数据 特点:数据以行为单位,每一个数据表示一个实体.每一行数据的属性都是一样的. 举例:关系型数据库中的表就是结构化数据. 处理方法:sql 2.半结构化数据 特点:结构化数 ...
- vue框架学习笔记(vue入门篇)
vue框架 - 构建用户界面的渐进式框架 - 采用自底层向上增量开发的设计 - 核心库只关注视图层 - 当与单文件组件和vue生态系统支持的库结合使用时,也完全能够为复杂的单页应用程序提供驱动 - v ...
- 第04组 Beta冲刺(1/5)
队名:new game 组长博客:戳 作业博客:戳 组员情况 鲍子涵(队长) 过去两天完成了哪些任务 验收游戏素材 学习Unity 2D Animation系统 接下来的计划 制作游戏需要的人物动画 ...
- STM32 F4xx Fault 异常错误定位指南
STM32 F407 采用 Cortex-M4 的内核,该内核的 Fault 异常可以捕获非法的内存访问和非法的编程行为.Fault异常能够检测到以下几类非法行为: 总线 Fault: 在取址.数据读 ...
- 避免python二维列表append一维列表时浅拷贝问题
原始问题: 由于浅拷贝原因,使得当a列表变动时,b列表也发生变动 解决办法: 如上图所示,添加的时候添加新列即可,类似新建一个列表,使得与原有列表a不共用同一个内存
- XML与DTD(够用)
1: 概述 1.1 什么是XML 1.2 三个重点 1.3规则 1.4 常用转义 2: Xml声明 XML 中,空格会被保留 XML 以 LF 存储换行 3:Xml标签 4:Xml元素 5:XML 属 ...
- 0x00007FFC8C5325E7 (ucrtbased.dll)处(位于 DataStructure.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。
此处为非“%s” 类型数据以“%s”类型打印错误. 需要仔细检查代码中数据类型错误.
- 面试官,我会写二分查找法!对,没有 bug 的那种!
前言科普 第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间. 2019 年的你,在面试的过程中能手写出没有 bug 的二 ...