BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治
题目链接:https://vjudge.net/problem/HYSBZ-3295
3295: [Cqoi2011]动态逆序对
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6517 Solved: 2295
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
1
5
3
4
2
5
1
4
2
Sample Output
2
2
1
样例解释
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
题解:
1.最核心的问题是:删除当前位置的数,会造成多少对逆序对的减少。
2.要统计删除当前数会造成多少对逆序对的减少,即需要统计:前面比它大的数的个数 + 后面比它小的数的个数 (前提是这些数没有被删除)。
3.由于题目还存在动态删除,则再为每个位置添加一个标志:Di,表明它是第几个被删除的。加上这个限制,就是一个三维偏序问题了。
4.以j为统计对象,sum[j]为删除位置j的数,所减少的逆序对。sum[j] = sum (i<j 且 Ai>Aj 且 Di>Dj)+ (j<i 且 Aj>Ai 且 Di>Dj)
5.得到sum数组之后,即知道删除当前位置的数,会造成多少对逆序对的减少。那么再算出初始的逆序对(不带删除,即二维偏序)即可。
写法一:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5+; struct node
{
int x, y, z;
};
node a[MAXN], b[MAXN], tmp[MAXN]; int n, m, c[MAXN];
int lowbit(int x) {return x&(-x);}
void add(int x, int val) {for(int i=x;i<=n;i+=lowbit(i)) c[i]+=val;}
int query(int x) {int ret=; for(int i=x;i>;i-=lowbit(i))ret+=c[i]; return ret;} int sum[MAXN], type;
void CDQ(int l, int r)
{
if(l==r) return; int mid = (l+r)>>;
CDQ(l, mid); CDQ(mid+, r);
int p1 = l, p2 = mid+;
for(int i = l; i<=r; i++)
{
if(p2>r||(p1<=mid&&a[p1].y>=a[p2].y)) b[i] = a[p1++];
else b[i] = a[p2++];
}
int cnt = ; //按删除顺序逆序排序了,所以先出现的更后删除
for(int i = l; i<=r; i++) //统计前面比它小的
{
a[i] = b[i];
if(a[i].x<=mid) add(a[i].z, ), cnt++;
else if(a[i].y!=INF) sum[a[i].y] += cnt-query(a[i].z);
}
for(int i = l; i<=r; i++)
if(a[i].x<=mid) add(a[i].z, -); for(int i = l; i<=r; i++) //统计后面比它大的
{
a[i] = b[i];
if(a[i].x>mid) add(a[i].z, );
else if(a[i].y!=INF) sum[a[i].y] += query(a[i].z-);
}
for(int i = l; i<=r; i++)
if(a[i].x>mid) add(a[i].z, -);
} int M[MAXN];
int main()
{
while(scanf("%d%d", &n,&m)!=EOF)
{
for(int i = ; i<=n; i++)
{
scanf("%d", &a[i].z);
M[a[i].z] = i;
a[i].x = i; a[i].y = INF;
}
for(int i = ; i<=m; i++)
{
int del;
scanf("%d", &del);
a[M[del]].y = i;
} LL ans = ;
memset(c, , sizeof(c));
for(int i = ; i<=n; i++)
{
ans += (i-)-query(a[i].z);
add(a[i].z, );
} memset(c, , sizeof(c));
memset(sum, , sizeof(sum));
CDQ(,n); printf("%lld\n", ans);
for(int i = ; i<m; i++)
{
ans -= sum[i];
printf("%lld\n", ans);
}
}
}
写法二:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5+; struct node
{
int x, y, z;
};
node a[MAXN], b[MAXN]; int n, m, c[MAXN];
int lowbit(int x) {return x&(-x);}
void add(int x, int val) {for(int i=x;i<=n;i+=lowbit(i)) c[i]+=val;}
int query(int x) {int ret=; for(int i=x;i>;i-=lowbit(i))ret+=c[i]; return ret;} int sum[MAXN], type;
void CDQ(int l, int r)
{
if(l==r) return; int mid = (l+r)>>;
CDQ(l, mid); CDQ(mid+, r);
int p1 = l, p2 = mid+;
for(int i = l; i<=r; i++)
{
if(p2>r||(p1<=mid&&a[p1].y>=a[p2].y)) b[i] = a[p1++];
else b[i] = a[p2++];
}
int cnt = ;
for(int i = l; i<=r; i++)
{
a[i] = b[i];
if(a[i].x<=mid) add(a[i].z, ), cnt++;
else if(a[i].y!=INF)
{
if(type) sum[a[i].y] += cnt-query(a[i].z);
else sum[a[i].y] += query(a[i].z-);
}
}
for(int i = l; i<=r; i++)
if(a[i].x<=mid) add(a[i].z, -);
} node tmp[MAXN];
int M[MAXN];
int main()
{
while(scanf("%d%d", &n,&m)!=EOF)
{
for(int i = ; i<=n; i++)
{
scanf("%d", &a[i].z);
M[a[i].z] = i;
a[i].y = INF;
}
for(int i = ; i<=m; i++)
{
int del;
scanf("%d", &del);
a[M[del]].y = i;
} LL ans = ;
memset(c, , sizeof(c));
for(int i = ; i<=n; i++)
{
ans += (i-)-query(a[i].z);
add(a[i].z, );
} memcpy(tmp, a, sizeof(tmp));
for(int i = ; i<=n; i++)
a[i].x = i;
memset(c, , sizeof(c));
type = ;
CDQ(,n); memcpy(a, tmp, sizeof(a));
reverse(a+,a++n);
for(int i = ; i<=n; i++)
a[i].x = i;
type = ;
CDQ(,n); printf("%lld\n", ans);
for(int i = ; i<m; i++)
{
ans -= sum[i];
printf("%lld\n", ans);
}
}
}
BZOJ3295 [Cqoi2011]动态逆序对 —— CDQ分治的更多相关文章
- [BZOJ3295][Cqoi2011]动态逆序对 CDQ分治&树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j,且 ...
- bzoj3295: [Cqoi2011]动态逆序对(cdq分治+树状数组)
3295: [Cqoi2011]动态逆序对 题目:传送门 题解: 刚学完cdq分治,想起来之前有一道是树套树的题目可以用cdq分治来做...尝试一波 还是太弱了...想到了要做两次cdq...然后伏地 ...
- BZOJ3295:[CQOI2011]动态逆序对(CDQ分治)
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- 【BZOJ3295】[Cqoi2011]动态逆序对 cdq分治
[BZOJ3295][Cqoi2011]动态逆序对 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依 ...
- bzoj3295 [Cqoi2011]动态逆序对 cdq+树状数组
[bzoj3295][Cqoi2011]动态逆序对 2014年6月17日4,7954 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数. ...
- [CQOI2011]动态逆序对 CDQ分治
洛谷上有2道相同的题目(基本是完全相同的,输入输出格式略有不同) ---题面--- ---题面--- CDQ分治 首先由于删除是很不好处理的,所以我们把删除改为插入,然后输出的时候倒着输出即可 首先这 ...
- 洛谷 P3157 [CQOI2011]动态逆序对 | CDQ分治
题目:https://www.luogu.org/problemnew/show/3157 题解: 1.对于静态的逆序对可以用树状数组做 2.我们为了方便可以把删除当成增加,可以化动为静 3.找到三维 ...
- BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]
RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...
- P3157 [CQOI2011]动态逆序对 CDQ分治
一道CDQ分治模板题简单来说,这道题是三维数点对于离线的二维数点,我们再熟悉不过:利用坐标的单调递增性,先按更坐标排序,再按纵坐标排序更新和查询时都直接调用纵坐标.实际上,我们是通过排序将二维中的一维 ...
随机推荐
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
Java垃圾回收机制(GC) 1.1 GC机制作用 1.2 堆内存3代分布(年轻代.老年代.持久代) 1.3 GC分类 1.4 GC过程 Java应用内存问题分析 2.1 Java内存划分 2.2 J ...
- es6 - 模板
'use strict'; // es5 let name = 'mrs'; let qb = 20; function logs() { return 'goods!'; } let html = ...
- beforeRouteLeave 实现vue路由拦截浏览器的需求,进行一系列操作 草稿保存等等
场景:为了防止用户失误点错关闭按钮等等,导致没有保存已输入的信息(关键信息).用法://在路由组件中: beforeRouteLeave (to, from, next) { if(用户已经输入信息) ...
- remove-duplicates-from-sorted-array-ii——去除重复
Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...
- swoole新手教程01-环境搭建及扩展安装
写在前面的废话 <swoole源代码分析>已经写了13章,整个swoole的核心架构基本都分析的差点儿相同了.于是心里一直以来想整理swoole的文档并写一份教程的想法就再度浮了出来. 实 ...
- 如何在cmd中启动redis
首先要指定redis安装的目录,然后输入: redis-server.exe redis.windows.conf 如果成功,则会出现redis的标志,失败的话 请转帖到: http://www.cn ...
- CentOS6下基于Nginx搭建mp4/flv流媒体服务器
CentOS6下基于Nginx搭建mp4/flv流媒体服务器(可随意拖动)并支持RTMP/HLS协议(含转码工具) 1.先添加几个RPM下载源 1.1)安装RPMforge的CentOS6源 [roo ...
- javascript onclick中post提交
对post提交进行封装: function post(URL, PARAMS) { var temp = document.createElement("form"); temp. ...
- Layout布局位置
- - GUILayout 这个本身就是用于自动布局的. 不用给定位置的,这也是它与GUI的区别所在.通常默认开始的位置是屏幕的左上角. 当然你也可以限定开始自动布局的位置.用 GUILayout.B ...
- Failed to load http://wantTOgo.com/get_sts_token/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://fromHere.com' is therefore not allowed access.
Failed to load http://wantTOgo.com/get_sts_token/: No 'Access-Control-Allow-Origin' header is presen ...