【BZOJ2141】排队(CDQ分治)

题面

题面以及树套树做法见这里

题解

大部分树套树/主席树这类题目都可以用整体二分/CDQ分治来做。

这题考虑一下,在不考虑修改的情况下

贡献是如何产生的?

我们发现是个二位偏序问题(或者说是一个逆序对修改版本)

现在有了一个修改,那么产生贡献的前提额外增加一个:时间。

既然变成了一个三位偏序问题

考虑\(CDQ\)分治

按照时间分治,块内按照\(x\)排序,考虑左侧对右侧的贡献:

维护当前数字(离散后)的一个值域树状数组

因为贡献有当前点作为左端点和右端点的两部分

所以,按照\(x\)正着加入树状数组一次,反着加入树状数组一次。

就求一下在当前时间之前,产生贡献的值就行了。

但是交换操作很不好办。

我们可以把一个交换操作改成两个删除操作和两个插入操作。

这样就可以交换的问题。

一个额外要注意的问题:排序的时候,如果\(x\)相同,一定还要按照修改的值排序,因为小的值同样可以更新大的值,否则会错。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 22222
#define lb(x) (x&(-x))
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Operator{int t,x,y,w,id;}q[MAX<<2],tmp[MAX<<2];
bool operator<(Operator a,Operator b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
int tot,len,S[MAX],a[MAX],n,m,tim;
int c[MAX],ans[MAX];
void add(int x,int w){while(x<=n)c[x]+=w,x+=lb(x);return;}
int getsum(int x){int ret=0;while(x)ret+=c[x],x-=lb(x);return ret;}
void CDQ(int l,int r)
{
if(l==r)return;
int mid=(l+r)>>1;
for(int i=l;i<=r;++i)
if(q[i].t<=mid)add(q[i].y,q[i].w);
else ans[q[i].id]+=q[i].w*(getsum(n)-getsum(q[i].y));
for(int i=l;i<=r;++i)
if(q[i].t<=mid)add(q[i].y,-q[i].w);
for(int i=r;i>=l;--i)
if(q[i].t<=mid)add(q[i].y,q[i].w);
else ans[q[i].id]+=q[i].w*getsum(q[i].y-1);
for(int i=l;i<=r;++i)if(q[i].t<=mid)add(q[i].y,-q[i].w);
int t1=l-1,t2=mid;
for(int i=l;i<=r;++i)
if(q[i].t<=mid)tmp[++t1]=q[i];
else tmp[++t2]=q[i];
for(int i=l;i<=r;++i)q[i]=tmp[i];
CDQ(l,mid);CDQ(mid+1,r);
}
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=S[i]=read();
sort(&S[1],&S[n+1]);len=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[len+1],a[i])-S;
for(int i=1;i<=n;++i)q[++tot]=(Operator){++tim,i,a[i],1,0};
n=len;m=read();
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
q[++tot]=(Operator){++tim,x,a[y],+1,i};
q[++tot]=(Operator){++tim,y,a[x],+1,i};
q[++tot]=(Operator){++tim,x,a[x],-1,i};
q[++tot]=(Operator){++tim,y,a[y],-1,i};
swap(a[x],a[y]);
}
sort(&q[1],&q[tot+1]);
CDQ(1,tim);
printf("%d\n",ans[0]);
for(int i=1;i<=m;++i)printf("%d\n",ans[i]+=ans[i-1]);
return 0;
}

【BZOJ2141】排队(CDQ分治)的更多相关文章

  1. BZOJ 2141: 排队 [CDQ分治]

    题意: 交换序列中两个元素,求逆序对 做分块做到这道题...一看不是三维偏序嘛.... 作为不会树套树的蒟蒻就写CDQ分治吧.... 对时间分治...x排序...y树状数组... 交换拆成两个插入两个 ...

  2. [国家集训队]排队 [cdq分治]

    题面 洛谷 和动态逆序对那道题没有什么区别 把一个交换换成两个删除和两个插入 #include <cstdio> #include <cstdlib> #include < ...

  3. bzoj 2141 : 排队 (cdq分治+bit)

    链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2141 思路: 其实就是求动态逆序对...cdq降维,用树状数组前后求两遍逆序对就好了 切水 ...

  4. BZOJ 2141 排队 (CDQ分治)

    [BZOJ2141]排队 这道题和动态逆序对比较像(BZOJ-3295 没做过的同学建议先做这题),只是删除操作变成了交换.解法:交换操作可以变成删除加插入操作,那么这题就变成了 (时间,位置,值)的 ...

  5. 【教程】简易CDQ分治教程&学习笔记

    前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦!       CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...

  6. BZOJ 2683 简单题 ——CDQ分治

    [题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...

  7. HDU5618 & CDQ分治

    Description: 三维数点 Solution: 第一道cdq分治...感觉还是很显然的虽然题目不能再傻逼了... Code: /*=============================== ...

  8. 初识CDQ分治

    [BZOJ 1176:单点修改,查询子矩阵和]: 1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 200 ...

  9. HDU5322 Hope(DP + CDQ分治 + NTT)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...

随机推荐

  1. 【转】 mysql使用federated引擎实现远程访问数据库(跨网络同时操作两个数据库中的表)

    原文转自:http://www.2cto.com/database/201412/358397.html 问题: 这里假设我需要在IP1上的database1上访问IP2的database数据库内的t ...

  2. 一起来做Chrome Extension《一些问题》

    目录 Unchecked runtime.lastError: The message port closed before a response wa received. 使用 eval Conte ...

  3. 详细讲解 A/B 测试关键步骤,快来检查下还有哪些疏漏的知识点

    作为一种对照实验方法,A/B 测试通过比较两个 (或多个) 不同版本之间的差异来验证假设是否正确.该方法将特定测试组从实验其余部分中独立出来,从而得出可靠结果.在被测人不知情且测试场景真实的情况下,A ...

  4. Siki_Unity_2-4_UGUI_Unity5.1 UI 案例学习

    Unity 2-4 UGUI Unity5.1 UI 案例学习 任务1-1:UGUI简介 什么是GUI: 游戏的开始菜单 RPG游戏的菜单栏.侧边栏和功能栏(比如背包系统.任务列表等) 设计用来控制移 ...

  5. RyuBook1.0案例三:REST Linkage

    REST Linkage 该小结主要介绍如何添加一个REST Link 函数 RYU本身提供了一个类似WSGI的web服务器功能.借助这个功能,我们可以创建一个REST API. 基于创建的REST ...

  6. MySQL Proxy和 Amoeba 工作机制浅析

    MySQL Proxy处于客户端应用程序和MySQL服务器之间,通过截断.改变并转发客户端和后端数据库之间的通信来实现其功能,这和WinGate 之类的网络代理服务器的基本思想是一样的.代理服务器是和 ...

  7. 【win10系统问题】远程桌面登录一次后,第二次登录看不到用户名和密码输入框

    [win10系统远程桌面登录问题] 远程桌面登录某服务器一次后,第二次登录看不到用户名和密码输入框 [解决方法] 在注册表里找到该路径下的远程服务器ip,删除即可: HKEY_CURRENT_USER ...

  8. Linux下的计算器(bc、expr、dc、echo、awk)知多少?

    linux 其他知识目录 原文链接:http://blog.chinaunix.net/uid-24673811-id-1760837.html linux下的三个命令可以用来作计算,下面一一讲解用法 ...

  9. python3【基础】-集合

    集合( set):把不同的元素组成一起形成集合,是python基本的数据类型. 集合元素(set elements):组成集合的成员(不可重复) class set(object) | set() - ...

  10. Alpha发布——美工+文案展示博客

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2283 文案: 学海无涯苦作舟,深海的远帆扬起成长的新程. 我将一滴水滴注 ...