传送门

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

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. 第七篇 Postman+Node.js+Newman+Jenkins实现自动化测试

    今天终于不咋忙了,学习整理一下一直想做却没实现的事儿,这事已经折磨团队半年之久了.因为项目是B端业务的测试,测试过程中需要生产大量的测试数据,而且都是跨多个系统的测试,对于后置流程的测试,这些同学往往 ...

  2. Python Web部署方式全汇总

    学过PHP的都了解,php的正式环境部署非常简单,改几个文件就OK,用FastCgi方式也是分分钟的事情.相比起来,Python在web应用上的部署就繁杂的多,主要是工具繁多,主流服务器支持不足. 在 ...

  3. redis主从配置+sentinel哨兵

    redis主从配置+sentinel哨兵 1:编译环境准备 1.1环境确认 Redis是一个开源.支持网络.基于内存.键值对存储数据库,使用ANSI C编写.所以在搭建Redis服务器时需要C语言的编 ...

  4. Python Tkinter-Event

    1.点击 from tkinter import * root=Tk() def printCoords(event): print(event.x,event.y) bt1=Button(root, ...

  5. Python基础知识-06-集合内存布尔False

    python其他知识目录 1.判断一个字符串中是否有敏感字符? #str: m_str="我叫魔降风云变" if "魔" in m_str: #判断指定字符是否 ...

  6. 如何把node更新到最新的稳定版本

    先装n,再用n把node升级到最新稳定版 $ npm install -g n $ n stable

  7. 子元素设置margin-top后,父元素跟随下移的问题

    子元素设置margin-top后,父元素跟随下移的问题 <!DOCTYPE html> <html lang="en"> <head> < ...

  8. 几个好用的php函数

    几个好用的php函数 1.PHP加密解密 PHP加密和解密函数可以用来加密一些有用的字符串存放在数据库里,并且通过可逆解密字符串,该函数使用了base64和MD5加密和解密. function enc ...

  9. Scrum立会报告+燃尽图(十月十八日总第九次):功能细化与数据库设计

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...

  10. 20181120-6 Beta阶段第2周/共2周 Scrum立会报告+燃尽图 03

    此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2411] 版本控制地址    [https://git.coding.n ...