传送门

果然前两天写完咕咕咕那个题的题解以后博客就开始咕咕咕了……

Description

给定整数 \(n\) 和两个 \(1~\sim~n\) 的排列 \(A,B\)。

\(m\) 个操作,操作有两种:

  • \(1~,~l1~,~r1~,~l2~,~r2\) 求\((\bigcup_{i=l1}^{r1} A_i)~\bigcap~(\bigcup_{i=l2}^{r2} B_i)\)
  • \(2~,~x~,~y\) 交换 \(B_x,~B_y\)

Input

第一行是两个正整数 \(n,m\)

下面两行,每行 \(n\) 个数, 给出排列 \(A,B\)

下面 \(m\) 行,每行一个操作

Output

对每个询问输出一行代表答案

Hint

\(0~\leq~n,m~\leq~2~\times~10^5\)

Solution

这不是hash+二维树状数组好题嘛!

然而因为一次操作有 \(4\) 次查询,相当于操作次数 \(10^6\),hash树状数组显然过不去= =

考虑如果给 \(B\) 重编号,\(B_i\) 代表原 \(B\) 中第 \(i\) 个元素在 \(A\) 中出现的位置,那么每次查询就等价于区间 \([l2, r2]\) 中有多少个数在 \([l1,r1]\) 内。于是这个问题被转化成了一个二维数点问题那我们去写hash+树状数组吧!,并且资瓷离线,于是考虑cdq分治过掉

这里记录一下待修改的cdq怎么写:将一次修改操作改为一个添加操作和一个删除操作。例如,交换 \(x, y\) 等价于删除 \((x,B_x),(y,B_y)\),并且加入 \((x,B_y),(y,B_x)\)。初始的序列以添加的形式给出

于是复杂度 \(O(n\log^2n)\),可以过掉本题

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 200010;
const int maxt = 1000010; struct Zay {
int id, x, y, mul, oppt, vec; inline void setit(ci _a, ci _b, ci _c, ci _d, ci _e, ci _f) {
id = _a; x = _b; y = _c; mul = _d; oppt = _e; vec = _f;
}
};
Zay opt[maxt], temp[maxt]; inline int lowbit(ci &x) {return x & -x;} int n, m, cnt, tot;
int CU[maxn], MU[maxn], ans[maxn], tree[maxt]; int ask(int);
void cdq(ci, ci);
void add(int, ci);
void query(const Zay&);
void update(const Zay&); int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
int a, l1, r1, l2, r2;
for (rg int i = 1; i <= n; ++i) {
a = 0; qr(a); CU[a] = i;
}
for (rg int i = 1; i <= n; ++i) {
a = 0; qr(a);// printf("QWQ%d\n", a);
++cnt; opt[cnt] = (Zay){opt[cnt - 1].id + 1, i, MU[i] = CU[a], 1, 0, 0};
}
while (m--) {
a = 0; qr(a);//printf("EM%d\n", a);
if (a == 1) {
l1 = r1 = l2 = r2 = 0; qr(l1); qr(r1); qr(l2); qr(r2); --l1; --l2;
int _pre = opt[cnt].id + 1;
opt[++cnt].setit(_pre, r2, r1, 1, 1, ++tot);
opt[++cnt].setit(_pre, l2, r1, -1, 1, tot);
opt[++cnt].setit(_pre, l2, l1, 1, 1, tot);
opt[++cnt].setit(_pre, r2, l1, -1, 1, tot);
} else {
l1 = r1 = 0; qr(l1); qr(r1);
int _pre = opt[cnt].id + 1;
opt[++cnt].setit(_pre, l1, MU[l1], -1, 0, 0);
opt[++cnt].setit(_pre, r1, MU[r1], -1, 0, 0);
std::swap(MU[l1], MU[r1]);
opt[++cnt].setit(_pre, l1, MU[l1], 1, 0, 0);
opt[++cnt].setit(_pre, r1, MU[r1], 1, 0, 0);
}
}
cdq(1, cnt);
for (rg int i = 1; i <= tot; ++i) qw(ans[i], '\n', true);
return 0;
} void cdq(ci l, ci r) {
if (l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid); cdq(mid + 1, r);
for (rg int i = l, ll = l, rr = mid + 1; i <= r; ++i) {
if (ll > mid) {
query(opt[rr]);
temp[i] = opt[rr++];
} else if (rr > r) {
update(opt[ll]);
temp[i] = opt[ll++];
} else if (opt[ll].x <= opt[rr].x) {
update(opt[ll]);
temp[i] = opt[ll++];
} else {
query(opt[rr]);
temp[i] = opt[rr++];
}
}
for (rg int i = l; i <= mid; ++i) if (!opt[i].oppt) {
add(opt[i].y, -opt[i].mul);
}
for (rg int i = l; i <= r; ++i) opt[i] = temp[i];
} inline void update(const Zay &_t) {
if (_t.oppt) return;
add(_t.y, _t.mul);
} inline void query(const Zay &_t) {
if (!_t.oppt) return;
ans[_t.vec] += _t.mul * ask(_t.y);
} void add(int x, ci v) {
while (x <= n) {
tree[x] += v;
x += lowbit(x);
}
} int ask(int x) {
int _ret = 0;
while (x) {
_ret += tree[x];
x -= lowbit(x);
}
return _ret;
}

Summary

cdq处理带修问题时,将修改变为删除和插入。

【cdq分治】【CF1093E】 Intersection of Permutations的更多相关文章

  1. [CF1093E]Intersection of Permutations

    [CF1093E]Intersection of Permutations 题目大意: 给定两个长度为\(n(n\le2\times10^5)\)的排列\(A,B\).\(m(m\le2\times1 ...

  2. CF1093E Intersection of Permutations 树状数组套权值线段树

    \(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...

  3. [CF1093E]Intersection of Permutations:树套树+pbds

    分析 裸的二维数点,博主用树状数组套平衡树写的,顺便pbds真好用. Update on 2018/12/20:再解释一下为什么是二维数点,第一维是\(la \leq i \leq ra\),第二维是 ...

  4. CF1093E Intersection of Permutations [分块 +bitset]

    大家好, 我非常喜欢暴力数据结构, 于是就用分块A了此题 分块题,考虑前缀和 \(b_i\) 表示 bitset 即 \(0\) ~ $i $ 出现过的数字,然后考虑直接暴力复制块然后前缀和,修改也很 ...

  5. CF 1093E Intersection of Permutations——CDQ分治

    题目:http://codeforces.com/contest/1093/problem/E 只能想到转化成查询一个区间里值在一个范围里的数的个数…… 没有想到这样适合用主席树套树状数组维护.不过据 ...

  6. Codeforces 1093E Intersection of Permutations [CDQ分治]

    洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...

  7. Codeforces 1093E Intersection of Permutations (CDQ分治+树状数组)

    题意:给你两个数组a和b,a,b都是一个n的全排列:有两种操作:一种是询问区间在数组a的区间[l1,r1]和数组b的区间[l2,r2]出现了多少相同的数字,另一种是交换数组b中x位置和y位置的数字. ...

  8. CF 1093 E. Intersection of Permutations

    E. Intersection of Permutations 链接 题意: 给定两个序列,询问第一个排列的[l1,r1]和第二个排列[l2,r2]中有多少个共同的数,支持在第二个排列中交换两个数. ...

  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. 【转载】IntelliJ IDEA 2017常用快捷键

    IntelliJ IDEA 是一款致力于提供给开发工程师沉浸式编程体验的IDE工具,所以在其中提供了很多方便高效的快捷键,一旦熟练掌握,整个开发的效率和体验将大大提升.本文就按照笔者自己日常开发时的使 ...

  2. 【snmp】Linux开启snmp及查询

    1.Linux snmp 1.安装snmp yum install -y net-snmp* 2.备份snmp配置 cp /etc/snmp/snmpd.conf /etc/snmp/snmpd.co ...

  3. MongoDB Chapter1:Introduction

    你是在防火墙后面吗? 为了继续本课程,您必须能够将计算机的传出请求发送到我们在MongoDB Atlas中设置的数据库服务器.这些服务器在Amazon AWS中的端口27017上运行. 请单击http ...

  4. Beta冲刺第二周王者荣耀交流协会第三次会议

    1.例会照片: 成员王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐 master:袁玥 2.时间跨度: 2017年11月19日 17:00 — 17:11,总计11分钟. 3.地 点: 一食堂 ...

  5. SSH新学,关于面向对象的看法

    流程:model-->dao-->service-->impService-->action 如果只是操作单个的一个表,比如user表,则都写到user的流程中 如果要操作俩个 ...

  6. 四则运算(Android)版

    实验题目: 将小学四则运算整合成网页版或者是Android版.实现有无余数,减法有无负数.... 设计思路: 由于学到的基础知识不足,只能设计简单的加减乘除,界面设计简单,代码量少,只是达到了入门级的 ...

  7. CS小分队第二阶段冲刺站立会议(5月27日)

    昨天成果:昨日有些小意外,导致没有按照原定计划工作.昨天为扫雷游戏增加了新的失败特效,只要玩家点到地雷,所有的地雷都会依次出现两帧的爆炸效果,并伴随声音. 今日计划:排除一些现有程序的bug.. 遇到 ...

  8. 0517 SCRUM团队项目4.0

    题目 1.准备看板.形式参考图4.2.任务认领,并把认领人标注在看板上的任务标签上.先由个人主动领任务,PM根据具体情况进行任务的平衡.然后每个人都着手实现自己的任务.3.为了团队合作愉快进展顺利,请 ...

  9. virsh 命令行管理虚拟机

    重用命令和选项 1:查看运行的虚拟机 virsh list   2:查看所有的虚拟机(关闭和运行的虚拟机) virsh list --all   3:连接虚拟机 virsh console +域名(虚 ...

  10. openssl 加密算法 CA 介绍

    首先对于tftp服务的简要使用说明 (1)yum安装:tftp.tftp-server   (2)启动tftp CentOS 6 service xinetd restart chkconfig tf ...