本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!

Description

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

Input

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

Output

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

Sample Input

5 4
1
5
3
4
2
5
1
4
2

Sample Output

5
2
2
1

样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

HINT

N<=100000 M<=50000

 
 
正解:CDQ分治
解题报告:
 
  CDQ分治裸题。其实也是树套树裸题,那么拿来当CDQ练手吧。
  考虑把删除变成倒着插入,那么我给每个坐标一个权值t,表示插入时间。那么第一个删除的t坐标当然是n,表示最后一个插入。然后为了方便,我们把未被删除的结点的t坐标从左往右设为1、2、3...
  考虑问题转换成了求对于(t0,x0,y0)满足t<t0,x<x0,y>y0的(t,x,y)的个数,这样就变成了三维偏序的裸题了。细节上有必要再说一下:
  首先CDQ分治之前按t排序,保证t已经有序,在每次分治内部,按x排序,正着扫整个区间的时候,对于[mid+1,r]的区间就在树状数组上查询大于他的y的值的数量;倒着扫,对于[mid+1,r]的区间就在树状数组上查询小于他的y的值的数量。因为左边的所有元素对于右边的所有元素而言,是可以肯定t要小一些的,所以CDQ分治就可以巧妙地解决三维偏序的问题。之后在递归处理左边右边就可以了,同样的做法。
  ps:我开始T了两发,犯的是写CDQ分治的常见错误,就是在分治里面清空了数组,事实上只要清除刚才打上去的标记就可以了,无需清空。
 
 
 //It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int inf = (<<);
const int MAXN = ;
int n,m,c[MAXN],match[MAXN],ans[MAXN];
LL Ans;
struct node{
int x,y,t;
int flag;
}a[MAXN],b[MAXN];
inline bool cmpx(node q,node qq){ if(q.x==qq.x) return q.y<qq.y; return q.x<qq.x; }
inline bool cmpt(node q,node qq){ return q.t<qq.t; }
inline void add(int x,int val){ while(x<=n) c[x]+=val,x+=x&(-x); }
inline int query(int x){int tot=; while(x>) tot+=c[x],x-=x&(-x); return tot; }
inline int getint()
{
int w=,q=; char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} inline void CDQ(int l,int r){
if(l>=r) return ; int mid=(l+r)>>,size=r-l+,cnt=;
for(int i=l;i<=mid;i++) b[++cnt]=a[i],b[cnt].flag=; for(int i=mid+;i<=r;i++) b[++cnt]=a[i],b[cnt].flag=;
sort(b+,b+cnt+,cmpx); //for(int i=1;i<=n;i++) c[i]=0;
for(int i=;i<=size;i++) {
if(b[i].flag==) add(b[i].y,);
else ans[b[i].t]+=query(n)-query(b[i].y);
}
for(int i=;i<=size;i++) if(b[i].flag==) add(b[i].y,-);
for(int i=size;i>=;i--) {
if(b[i].flag==) add(b[i].y,);
else ans[b[i].t]+=query(b[i].y);
}
for(int i=;i<=size;i++) if(b[i].flag==) add(b[i].y,-);
CDQ(l,mid); if(mid<r) CDQ(mid+,r);
} inline void work(){
n=getint(); m=getint(); for(int i=;i<=n;i++) { a[i].x=i; a[i].y=getint(); match[a[i].y]=i; } int cc=n,x;
for(int i=;i<=m;i++) { x=getint(); a[match[x]].t=cc--; } for(int i=;i<=n;i++) if(a[i].t==) a[i].t=cc--;
sort(a+,a+n+,cmpt); CDQ(,n);
for(int i=;i<=n;i++) Ans+=ans[i];
for(int i=n;i>n-m;i--) {
printf("%lld\n",Ans);
Ans-=ans[i];
}
} int main()
{
work();
return ;
}

BZOJ3295 [Cqoi2011]动态逆序对的更多相关文章

  1. bzoj3295 [Cqoi2011]动态逆序对 cdq+树状数组

    [bzoj3295][Cqoi2011]动态逆序对 2014年6月17日4,7954 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. ...

  2. bzoj3295[Cqoi2011]动态逆序对 树套树

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

  3. 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)

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

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

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

  5. bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...

  6. BZOJ3295: [Cqoi2011]动态逆序对(树状数组套主席树)

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

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

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

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

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

  9. [bzoj3295][Cqoi2011]动态逆序对_主席树

    动态逆序对 bzoj-3295 Cqoi-2011 题目大意:题目链接. 注释:略. 想法:直接建立主席树. 由于是一个一个删除,所以我们先拿建立好的root[n]的权值线段树先把总逆序对求出来,接着 ...

  10. bzoj3295: [Cqoi2011]动态逆序对(树套树)

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

随机推荐

  1. 04传智_jbpm与OA项目_部门模块改进_直接在BaseAction中实现ModelDriven<T>

    这个项目是用Struts2做的,我这里单独写了一个BaseAction,用来存放所有的功能模块的Action的公共部分, 刚开始的做法是这个BaseAction只会继承ActionSupport 并不 ...

  2. BZOJ 4241 历史研究

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  3. .NET 4.0 任务(Task)

    随着 .NET 4.0的到来,她与以前各版本的一个明显差别就是并行功能的增强,以此来适应这个多核的世界.于是引入了一个新概念---任务,作为支持并行运算的重要组成部分,同时,也作为对线程池的一个补充和 ...

  4. scala 学习笔记(06) OOP(下)多重继承 及 AOP

    一.多继承 上篇trait中,已经看到了其用法十分灵活,可以借此实现类似"多重继承"的效果,语法格式为: class/trait A extends B with C with D ...

  5. Java并发编程实战(使用synchronized实现同步方法)

    本文介绍java最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问,如果一个对象已用synchronized关键字声明,那么只有一个执行线程允许去访问它,其它试图访问这个对 ...

  6. xmind 使用备忘

    快捷键: shift+enter 编辑文字时回车换行 enter 快速建立同级主题(纵向) tab 快速建立子主题(横向) F4 插入注释 alt+左键+移动 拖动 shift+左键+移动 将元素脱离 ...

  7. 理解JavaScript中的参数传递 - leetcode189. Rotate Array

    1.关于leetcode 这是第一篇关于leetcode的题解,就先扯点关于leetcode的话. 其实很早前就在博客园看到过leetcode一些题解,总以为跟一般OJ大同小异,直到最近点开了一篇博文 ...

  8. JQuery 图片略缩与弹出预览 jqthumb fancybox

    弹出框插件-FANCYBOXhttp://www.jq22.com/jquery-info28 jqthumb.js缩略图插件 http://www.ijquery.cn/?p=798

  9. 如何阻止SELECT * 语句

    我们每个人都知道是个不好的做法,但有时我们还是要这样做:我们执行SELECT * 语句.这个方法有很多弊端: 你从你的表里返回每个列,甚至后期加的列.想下如果你的查询里将来加上了VARCHAR(MAX ...

  10. 在Go语言中使用JSON(去掉空字段)

    Encode 将一个对象编码成JSON数据,接受一个interface{}对象,返回[]byte和error: func Marshal(v interface{}) ([]byte, error) ...