3295: [Cqoi2011]动态逆序对

Time Limit: 10 Sec  Memory Limit: 128 MB

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

题解:

啊啊啊这道题真的是差点把自己打死

跟zyfdalao分享了一下思路然后他就按我的思路A了可是我自己却不会了

如果你是树套树玩家,请移步:http://www.cnblogs.com/TSHugh/p/7001884.html

在具体写题解之前,我要分享一个面对瓶颈很好的做法(我这样反复理了三遍,思路一遍比一遍清晰...遇到瓶颈的时候真的很推荐这样做):

思路不通了把所有已知条件再列出来一边,写清变量之间的关系和限制,并且针对每一个条件写出解决方案和打法

感觉凌乱的代码段就删掉重打一遍,用的总时间一定会比死调下去少

首先一个小优化:把val变成n-val+1,这样原来的逆序对就变成了现在的顺序对,个人感觉更加好操作.

我们考虑,我们可以利用树状数组求出一开始总的逆序对数,并且同时利用树状数组求出以每个位置为开头和结尾的逆序对个数,

我们设num数组表示这个数目,num[0][i]表示以i位置结尾的逆序对个数,num[1][i]表示以i位置开头的逆序对个数.

这样的话,每次我们先输出当前的总数,再减去num[0][i]+num[1][i],然后...

我们发现有一些不对,如果原来形成的逆序对的另外那个数已经被删除了,那么这一对就不应该被减去

所以我们考虑再计算一个delta表示这个增量:

其中delta[0][i]表示以i位置结尾,但是另外那个数比i删除的早的逆序对个数,

delta[1][i]表示以i位置开头,但是另外那个数比i删除的早的逆序对个数.

接下来我们考虑什么样的数对(i,j)会被记入delta

如果设i位置的数的删除时间是tim[i](没有被删除的数的删除时间顺次设成m+1~n即可,他们的delta不会被记入答案)

设i位置的数值是val[i](这里的val已经进行了n-val+1取反操作)

那么delta[0][i]里的数应该满足:

tim[i]>tim[j]

val[i]>val[j]

i>j

delta[1][i]里的数应该满足:

tim[i]>tim[j]

val[i]<val[j]

i<j

那么上面这两组约束条件(尤其是第一组)很像一个三维偏序的统计问题.

的确如此,我们只需要用CDQ分治统计一下符合条件的数对数即可.

拿我的思路来说,我们可以让时间有序,给下标排序,用树状数组维护权值val,

这样跑两遍CDQ统计符合条件的偏序对数,就能分别计算delta[0][i]和delta[1][i]

最后输出答案时,先输出答案ans,然后给ans减去num[0][i]+num[1][i],再加上delta[0][i]+delta[1][i],这样就能正确的维护逆序对数了,

代码实现:

 #include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=,M=;
struct node
{
int tim,val,pos;
node (int a=,int b=,int c=){tim=a,val=b,pos=c;}
}q[N];
int cnt,n,m,a[N],match[N],step[M];
bool vis[N];
LL delta[][N],num[][N],bit[N];
inline int lowbit(int a){return a&-a;}
inline void add(int a,LL b)
{while(a<=n)bit[a]+=b,a+=lowbit(a);}
inline LL sum(int a)
{LL ret=;while(a)ret+=bit[a],a-=lowbit(a);return ret;}
inline void gsum0()
{
for(register int i=;i<=n;++i)
num[][i]=sum(a[i]),add(a[i],);
memset(bit,,sizeof(bit));
}
inline void gsum1()
{
for(register int i=n;i;--i)
num[][i]=sum(a[i]),add(,),add(a[i],-);
memset(bit,,sizeof(bit));
}
inline void readin()
{
register int i;scanf("%d%d",&n,&m);
for(i=;i<=n;++i)
scanf("%d",&a[i]),a[i]=n-a[i]+,match[a[i]]=i;
gsum0();gsum1();
for(i=;i<=m;++i)
scanf("%d",&step[i]),step[i]=n-step[i]+,vis[step[i]]=;
}
inline bool mt1(const node &a,const node &b){return a.pos<b.pos;}
inline bool mt2(const node &a,const node &b){return a.tim<b.tim;}
inline void CDQ0(int l,int r)
{
if(l==r)return;
register int mi=l+r>>,i;
CDQ0(l,mi);CDQ0(mi+,r);
sort(q+l,q+r+,mt1);
for(i=l;i<=r;++i)
if(q[i].tim<=mi)add(q[i].val,);
else delta[][q[i].tim]+=sum(q[i].val);
for(i=l;i<=r;++i)
if(q[i].tim<=mi)add(q[i].val,-);
}
inline void CDQ1(int l,int r)
{
if(l==r)return;
register int mi=l+r>>,i;
CDQ1(l,mi);CDQ1(mi+,r);
sort(q+l,q+r+,mt1);
for(i=r;i>=l;--i)
if(q[i].tim<=mi)add(,),add(q[i].val,-);
else delta[][q[i].tim]+=sum(q[i].val);
for(i=r;i>=l;--i)
if(q[i].tim<=mi)add(,-),add(q[i].val,);
}
int main()
{
register int i;readin();
for(i=;i<=m;++i)
q[++cnt]=node(cnt,step[i],match[step[i]]);
for(i=;i<=n;++i)
if(!vis[a[i]])q[++cnt]=node(cnt,a[i],i);
CDQ0(,n),sort(q+,q+n+,mt2),CDQ1(,n);
LL ans=;int pos;
for(i=;i<=n;++i)ans+=num[][i];
for(i=;i<=m;++i)
{
printf("%lld\n",ans),pos=match[step[i]],
ans-=(num[][pos]+num[][pos]),
ans+=(delta[][i]+delta[][i]);
}
}

[BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树的更多相关文章

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

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

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

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

  3. BZOJ3295:[CQOI2011]动态逆序对(CDQ分治)

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

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

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

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

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

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

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

  7. [BZOJ3295] [Cqoi2011]动态逆序对(带修改主席树)

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

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

    洛谷上有2道相同的题目(基本是完全相同的,输入输出格式略有不同) ---题面--- ---题面--- CDQ分治 首先由于删除是很不好处理的,所以我们把删除改为插入,然后输出的时候倒着输出即可 首先这 ...

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

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

随机推荐

  1. Oracle中Date和Timestamp的区别

    Date和Timestamp精度不一样: 01)Timestamp精确到了秒的小数点(如:2018-11-13 16:40:03.698): 02)Date只精确到整数的秒(如:2018-11-13 ...

  2. iFIERO - (一) 宇宙大战 SPACE BATTLE — 场景SCENE、SpriteKit精灵、PARTICLE粒子及背景音乐

    开始游戏教程前,首先介绍一下SpriteKit是什么?SpriteKit提供了一个图形渲染和动画的基础结构,你可以使用它让任意类型的纹理图片或者精灵动起来.SpriteKit使用渲染循环,利用图形硬件 ...

  3. 用shell实现bat批处理的pause命令-追加改进

    我参考了这个文章:用shell实现bat的pause http://linux-wiki.cn/wiki/zh-hans/%E7%94%A8shell%E5%AE%9E%E7%8E%B0bat%E7% ...

  4. Git----01介绍&下载&安装&创建本地仓库

    一.Git介绍 1.0.Git是分布式版本控制工具 1.1.历史 Linux 内核开源项目有着为数众广的参与者.绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2 ...

  5. gulp: Did you forget to signal async completion? 解决方案

    背景 学习gulp的前端自动化构建,按照示例代码,跑了一个简单的task,控制台打出如下提示: The following tasks did not complete: testGulp Did y ...

  6. Python处理PDF和Word文档常用的方法

    Python处理PDF和Word文档的模块是PyPDF2,使用之前需要先导入. 打开一个PDF文档的操作顺序是:用open()函数打开文件并用一个变量来接收,然后把变量给传递给PdfFileReade ...

  7. 模块-Memcached、Redis

    目录 Mecache 安装 使用 Redis 安装 Python操作Redis 操作模式 连接池 操作 String Hash List Set sort set 其他常用操作 管道 发布订阅 sen ...

  8. Flask之笔记集合

    目录 一.简述 二.基本使用 三.配置文件 四.路由系统 2.自定义正则路由 五.模版语言 六.请求和响应 七.Session 2.自定义session 八.蓝图 九.message 十.中间件 十一 ...

  9. Vue 入门之概念

    Vue 简介 Vue 是一个前端的双向绑定类的框架,发音[读音 /vjuː/, 类似于 [view].新的 Vue 版本参考了 React 的部分设计,当然也有自己独特的地方,比如 Vue 的单文件组 ...

  10. Enterprise Library 2.0 参考源码索引

    http://www.projky.com/entlib/2.0/Microsoft/Practices/EnterpriseLibrary/Caching/BackgroundScheduler.c ...