【cdq分治】【CF1093E】 Intersection of Permutations
果然前两天写完咕咕咕那个题的题解以后博客就开始咕咕咕了……
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的更多相关文章
- [CF1093E]Intersection of Permutations
[CF1093E]Intersection of Permutations 题目大意: 给定两个长度为\(n(n\le2\times10^5)\)的排列\(A,B\).\(m(m\le2\times1 ...
- CF1093E Intersection of Permutations 树状数组套权值线段树
\(\color{#0066ff}{ 题目描述 }\) 给定整数 \(n\) 和两个 \(1,\dots,n\) 的排列 \(a,b\). \(m\) 个操作,操作有两种: \(1\ l_a\ r_a ...
- [CF1093E]Intersection of Permutations:树套树+pbds
分析 裸的二维数点,博主用树状数组套平衡树写的,顺便pbds真好用. Update on 2018/12/20:再解释一下为什么是二维数点,第一维是\(la \leq i \leq ra\),第二维是 ...
- CF1093E Intersection of Permutations [分块 +bitset]
大家好, 我非常喜欢暴力数据结构, 于是就用分块A了此题 分块题,考虑前缀和 \(b_i\) 表示 bitset 即 \(0\) ~ $i $ 出现过的数字,然后考虑直接暴力复制块然后前缀和,修改也很 ...
- CF 1093E Intersection of Permutations——CDQ分治
题目:http://codeforces.com/contest/1093/problem/E 只能想到转化成查询一个区间里值在一个范围里的数的个数…… 没有想到这样适合用主席树套树状数组维护.不过据 ...
- Codeforces 1093E Intersection of Permutations [CDQ分治]
洛谷 Codeforces 思路 一开始想到莫队+bitset,发现要T. 再想到分块+bitset,脑子一抽竟然直接开始写了,当然也T了. 最后发现这就是个裸的CDQ分治-- 发现\(a\)不变,可 ...
- Codeforces 1093E Intersection of Permutations (CDQ分治+树状数组)
题意:给你两个数组a和b,a,b都是一个n的全排列:有两种操作:一种是询问区间在数组a的区间[l1,r1]和数组b的区间[l2,r2]出现了多少相同的数字,另一种是交换数组b中x位置和y位置的数字. ...
- CF 1093 E. Intersection of Permutations
E. Intersection of Permutations 链接 题意: 给定两个序列,询问第一个排列的[l1,r1]和第二个排列[l2,r2]中有多少个共同的数,支持在第二个排列中交换两个数. ...
- HDU5322 Hope(DP + CDQ分治 + NTT)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can ...
随机推荐
- [转]50 Tips for Working with Unity (Best Practices)
About these tips These tips are not all applicable to every project. They are based on my experience ...
- java获取IP地址
最近在一个多系统集成的项目中,由于跳转路径含IP地址,每次IP改了重启项目都得改好多地方,甚是麻烦.刚在网上了解到java获取IP地址,给大家分享下: 首先要导入jar包 request.getRem ...
- [C++基础] 成员变量的初始化顺序
转载链接:https://blog.csdn.net/qq_37059483/article/details/78608375 1.成员变量在使用初始化列表初始化时,只与定义成员变量的顺序有关,与构造 ...
- Paper Reading - Deep Captioning with Multimodal Recurrent Neural Networks ( m-RNN ) ( ICLR 2015 ) ★
Link of the Paper: https://arxiv.org/pdf/1412.6632.pdf Main Points: The authors propose a multimodal ...
- .net mvc5 不同view()的视图 代码
public class Test { public int id { set; get; } public string name { set; get; } } public ActionResu ...
- Python基础知识-06-集合内存布尔False
python其他知识目录 1.判断一个字符串中是否有敏感字符? #str: m_str="我叫魔降风云变" if "魔" in m_str: #判断指定字符是否 ...
- “我爱淘”第二冲刺阶段Scrum站立会议3
完成任务: 完成了注册界面的设计,以及部分代码,但是还没有完成服务器端的添加功能. 计划任务: 将注册功能实现了它,可以对数据库进行添加,在客户端实现分类功能,通过学院的分类查看书籍. 遇到问题: 分 ...
- HDU 4489 The King’s Ups and Downs dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4489 The King's Ups and Downs Time Limit: 2000/1000 ...
- 《高性能JavaScript》学习笔记——日更中
------------------2016-7-20更------------------ 最近在看<高性能JavaScript>一书,里面当中,有讲很多提高js性能的书,正在看的过程中 ...
- (双人项目)四则运算 组员:杨钰宁 闫浩楠 开发语言:Python。
需求分析:1.适用人群:小学生. 2.能进行“+,—,*,/” 的四则运算.难度可以随时修改. 3.提交试卷后可以显示所得分数并显示错题个数. 4.可以显示答对的题及其打错的题的序号. 代码如下: i ...