luogu P3157 [CQOI2011]动态逆序对(CDQ分治)
题目描述
对于序列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分治)的更多相关文章
- LUOGU P3157 [CQOI2011]动态逆序对(CDQ 分治)
传送门 解题思路 cdq分治,将位置看做一维,修改时间看做一维,权值看做一维,然后就转化成了三维偏序,用排序+cdq+树状数组.注意算删除贡献时要做两次cdq,分别算对前面和后面的贡献. #inclu ...
- 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治
题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...
- P3157 [CQOI2011]动态逆序对 CDQ分治
一道CDQ分治模板题简单来说,这道题是三维数点对于离线的二维数点,我们再熟悉不过:利用坐标的单调递增性,先按更坐标排序,再按纵坐标排序更新和查询时都直接调用纵坐标.实际上,我们是通过排序将二维中的一维 ...
- P3157 [CQOI2011]动态逆序对 (CDQ解决三维偏序问题)
P3157 [CQOI2011]动态逆序对 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任 ...
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...
- bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)
3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...
- BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3295 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 1 ...
- [Luogu P3157][CQOI2011]动态逆序对 (树套树)
题面 传送门:[CQOI2011]动态逆序对 Solution 一开始我看到pty巨神写这套题的时候,第一眼还以为是个SB题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...
随机推荐
- java中return在Try-Catch中的执行顺序
我们知道return会结束此方法并返回指定值.以及在Try-catch-finally中无论try代码块中有没有异常finally中的代码时都会被执行的.但是如果return包含在try-catch- ...
- 百度编辑器UEditor修改成支持物理路径
一.前言 我虽然工作了2年.有快1年没有做后台的开发了.最近要写个新项目用到富文本编辑器,然后选择用了百度的UEditor.在使用过程中感觉有些不太好.然后就自己手动改一下源码,写得不好请见谅.这只是 ...
- jqGrid系列知识
1.获取选中到行的ID var rowKey = jQuery(grid_selector).getGridParam("selrow"); 2.获取选中行除ID之外的数据 var ...
- 《Unix环境高级编程》读书笔记 第11章-线程
1. 引言 了解如何使用多个控制线程在单进程环境中执行多个任务. 不管在什么情况下,只要单个资源需要在多个用户键共享,就必须处理一致性问题. 2. 线程概念 典型的Unix进程可以看成只有一个控制线程 ...
- 预测一下web前端未来的6个趋势
2018年前端技术的发展也将进入到一个相对稳定的阶段, 就前端主流技术框架的发展而言,过去的几年里发展极快,在填补原有技术框架空白和不足的同时也渐渐趋于成熟. 未来前端在已经趋向成熟的技术方向上面将会 ...
- js对象追加到数组里
描述:将一个点击事件得到的对象追加到数组里 做法:全局声明一个数组,,在对象的点击事件里将得到的对象追加到数组 change(a){ arr.push(a) console.log(arr) var ...
- [agc008d]kth-k
题意: 给你一个长度为N的整数序列X,构造一个整数序列a满足: 1.a的长度为$N^2$,且1~N中每个数字恰好出现N次: 2.数字i在a中第i次出现的位置为$X_i$: 如果不能构造输出“No”,否 ...
- vue项目的webpack4.X配置
这两天摆弄webpack,躺过很多坑,直到今天看了一位博主的文章才得以解决.他对配置中的各个部分做说明. 下面的配置99.9%抄自博主: https://www.cnblogs.com/nianyif ...
- springMVC接受数组
var obj = {}; var params = new Array(); var selected1 = $('#datatable').DataTable().rows('.selected' ...
- Java取得环境变量和系统属性
取得所有的环境变量 public class GetEnvAndProp { public static void main(String[] args) { Map<String, Strin ...