[BZOJ3295][Cqoi2011]动态逆序对(分块重建)

原创 2016年06月02日 11:13:01

题意:一个排列,每次删除一个数,求每次删除后的逆序对的数量。

正确姿势请移步 http://blog.csdn.net/u011542204/article/details/50571409

将操作分成根号M段,然后每段内的操作按下标排序,计算它前面的比他小的和它后面的比他大的。有一个问题就是同一个块当中的没有被减掉,由于一个块内只有根号M个操作,暴力减掉即可。

如果要在线的话将那个排序变成主席树即可。

时间复杂度O(M*logM*sqrt(n)),空间O(n),适当地将块调大一点会快一点。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
#define LL long long
using namespace std;
const int MAXN = 100005;
int a[MAXN], pos[MAXN], N, M, bsz, b[MAXN], cnt, c[MAXN], r;
inline void add(int i,int x) { for(;i<=N;i+=i&-i) c[i]+=x; }
inline int qsum(int i) { for(r=0;i;i^=i&-i) r+=c[i]; return r; }
LL val[MAXN];
struct qua{
	int p,id;
	bool operator<(const qua&b)const{return p<b.p;}
}q[MAXN];
int main()
{
	scanf("%d%d",&N,&M);
	rep(i,1,N) scanf("%d",a+i),pos[a[i]]=i;
	bsz = ceil(sqrt(M+0.5))+0.1; bsz<<=1;
	if (bsz>M) bsz = M;
	rep(i,1,M) scanf("%d",b+i);
	LL tot = 0;
	erp(j, N, 1) tot+=qsum(a[j]-1), add(a[j],1);
	for (int i=1, nex, p; i<=M; i+=bsz)
	{
		cnt = 0;
		nex = min(M, i+bsz-1);
		rep(j, i, nex) q[++cnt]=(qua){pos[b[j]],j};
		sort(q+1,q+cnt+1);
		p = 1;
		int num = 0;
		rep(j,0,N) c[j]=0;
		rep(j, 1, N)
		{
			if (p>cnt) break;
			if (a[j]<0) continue;
			if (j==q[p].p) val[q[p].id]+=num-qsum(a[j]), p++;
			add(a[j],1), num++;
		}
		p = cnt;
		rep(j,0,N) c[j]=0;
		erp(j, N, 1)
		{
			if (p<1) break;
			if (a[j]<0) continue;
			if (j==q[p].p) val[q[p].id]+=qsum(a[j]), p--;
			add(a[j],1);
		}
		rep(j, i, nex)
		{
			rep(k, i, j-1) if (pos[b[k]]<pos[b[j]]&&b[k]>b[j]||pos[b[k]]>pos[b[j]]&&b[k]<b[j]) val[j]--;
			printf("%lld\n", tot); tot -= val[j];
		}
		rep(j, i, nex) a[pos[b[j]]]=-1;
	}
	return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

[BZOJ3295] [Cqoi2011]动态逆序对 (树套树)or(CDQ分治)

题意:N个数的排列,M次操作,每次求当前的逆序对数量并删掉一个数。 先说一下cdq分治做法。(5960kb,1.4s) 网上很多题解,我都看不懂(其实很多人的程序几乎是一样的,就改了一下变...
  • u011542204
  • u011542204
  • 2016年01月23日 22:16
  • 2576

bzoj3295树状数组套主席树

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 5144  Solved: 1730 [Submit...
  • lvzelong2014
  • lvzelong2014
  • 2017年08月05日 14:15
  • 228

BZOJ 3295 动态逆序对 CDQ分治

BZOJ 3295 动态逆序对 CDQ分治
  • PoPoQQQ
  • PoPoQQQ
  • 2014年08月22日 20:38
  • 3227

BZOJ3295/CQOI2011 题解(CDQ分治)

题目如下: Description 对于序列A,它的逆序对数定义为满足ij,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统...
  • qyfl806
  • qyfl806
  • 2017年03月16日 14:32
  • 201

【bzoj3295】[Cqoi2011]动态逆序对 树状数组套主席树

Description对于序列A,它的逆序对数定义为满足iInput输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个...
  • LOI_DQS
  • LOI_DQS
  • 2016年04月05日 21:57
  • 786

[BZOJ2141]排队(分块+树状数组求逆序对)

最纯粹的孤独,总是出自大师之门。
  • Clove_unique
  • Clove_unique
  • 2016年04月01日 11:34
  • 651

bzoj3295【CDQ分治】

答案在long long 范围内 #include #include #include #include #include using namespace std; typedef long lon...
  • stony_oi
  • stony_oi
  • 2016年12月11日 19:22
  • 262

bzoj3295(线段树套平衡树(treap))

3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 861  Solved: 287 [Submit][...
  • cq_phqg
  • cq_phqg
  • 2014年09月02日 17:41
  • 1124

[BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)

总有一天 能让这欢喜的歌声传到你身边
  • Clove_unique
  • Clove_unique
  • 2016年04月28日 14:10
  • 670

bzoj3295【CQOI2011】动态逆序对

CDQ分治+树状数组
  • AaronGZK
  • AaronGZK
  • 2016年05月14日 00:10
  • 5005
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[BZOJ3295][Cqoi2011]动态逆序对(分块重建)
举报原因:
原因补充:

(最多只允许输入30个字)