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题:这不直接开倒车线段树统计就完成了吗? 然后冷静思考了一分钟,猛然发现单纯的 ...
随机推荐
- QT笔记 -- (6) opengl
参考 http://blog.csdn.net/myths_0/article/details/24431597 用glut绘制一个茶壶 一句话,继承QGLWidget,实现下面三个函数,用子类定义窗 ...
- C++ 获取某一文件夹下的所有文件名
//********************************************************************** // Method: 获取文件夹下所有文件 // Fu ...
- 3ds Max修改桌面快捷方式为中文语言
通过上篇教程的学习,我们已经会切换3ds Max 2018的界面语言了,相关内容可参阅3ds Max如何设置中文界面.但是如果每次都要从开始菜单进行操作,岂不麻烦?简单一点,可以在桌面添加3ds Ma ...
- Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现
前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...
- Mint-UI 没有样式?
如果用mint-ui组件,如toast没有样式,是因为没有映入全局样式和导入MintUI 方法如下: 1.安装 npm install mint-ui -S -S表示 --save 2.在main.j ...
- 物理机安装CentOS7
最近捯饬到一台很老的机器,装Win7吧卡的不要不要的,思来想去的,搞个CentOS来玩玩,玩玩python的一些个人项目,一般装机啥的,都要做启动盘啥的,但是,这个都的话有很多网友已经分享了很多好的文 ...
- linux下安装jdk跟tomcat
文章参考 https://www.cnblogs.com/geekdc/p/5607100.html Linux服务器安装jdk+tomcat https://baijiahao.baidu ...
- 洛谷 P1169 [ZJOI2007]棋盘制作 (悬线法)
和玉蟾宫很像,条件改成不相等就行了. 悬线法题目 洛谷 P1169 p4147 p2701 p1387 #include<cstdio> #include<algorithm& ...
- Linux入门基础(一)
UNIX/Linux 本身是没有图形界面的,我们通常在 UNIX/Linux 发行版上看到的图形界面实际都只是运行在 Linux 系统之上的一套软件XFree86,现在则是 xorg(X.Org),而 ...
- [转] 经典排序算法 - 基数排序Radix sort
原理类似桶排序,这里总是需要10个桶,多次使用 首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数 例如 待排序数组[62,14,59,88,16]简单点五个数字 分 ...