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 ...
随机推荐
- 0day2安全——笔记3
第二章 函数调用约定 不同的操作系统,语言和编译器调用函数的原理差不多,但是具体的调用约定有差异. C语言VC++编译的函数传参顺序如下图所示(默认使用__stdcall调用约定) 函数调用步骤(__ ...
- Python gc
Python gc Python gc 模块提供垃圾回收器的接口 关于 Python 垃圾回收 <- 点击查看 官方文档:https://docs.python.org/3/library/gc ...
- Python连载50-贪婪匹配、XPath介绍
一.贪婪和非贪婪 1.贪婪:尽可能多的匹配,(*)表示贪婪匹配 2.非贪婪:找到符合条件的最小内容即可,(?)表示非贪婪 3.正则默认使用贪婪匹配 import re title = u"& ...
- 【Linux命令】centos防火墙使用和配置
目录 firewalld iptables Linux中的防火墙(iptables,firewalld,ip6tables,ebtables).这些软件本身并不具备防火墙功能,他们的作用都是在用户空间 ...
- 创 PHP RSA2 签名算法
什么是RSA2 ? RSA2 是在原来SHA1WithRSA签名算法的基础上,新增了支持SHA256WithRSA的签名算法. 该算法比SHA1WithRSA有更强的安全能力. 为了您的应用安 ...
- 支付签名 MD5Util 排序工具类
package com.skynet.wechat.wxPay.common; import java.security.MessageDigest; import java.util.Iterato ...
- 搭建Jupyter学习环境
`python notebook`是一个基于浏览器的python数据分析工具,使用起来非常方便,具有极强的交互方式和富文本的展示效果.jupyter是它的升级版,它的安装也非常方便,一般`Anacon ...
- 全栈工程师对Python面试中is和==区别的详细解说!看完真的学到了!
面试实习生的时候,当问到 is 和 == 的区别时,很多同学都答不上来,搞不清两者什么时候返回一致,什么时候返回不一致.本文我们来看一下这两者的区别. 我们先来看几个例子: a = "hel ...
- 易优CMS:【小白学标签】之empty的基础用法
[基础用法] 名称:empty 功能:判断某个变量是否为空,可以嵌套到任何标签里面使用,比如:channel.type等 语法: {eyou:empty name='$eyou.field.seo_t ...
- shell 编程练习题2
需求1:使用root用户清空/var/log/messages日志,并每次执行保留最近100行 1.必须是root用户 2.需要保留最后100行 [root@manager if]# cat ...