【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 ...
随机推荐
- XSS 注入检查点
如果你有个论坛,一般你会很注意用户发帖的注入问题,往往这个地方不会被注入,因为开发特别照顾.原则上XSS都是用户输入的,但是许多边角还是容易忽略.枚举一些检查点. 分页 分页通用组件获取url,修改p ...
- cs231n学习笔记(一)计算机视觉及其发展史
在网易云课堂上学习计算机视觉经典课程cs231n,觉得有必要做个笔记,因为自己的记性比较差,留待以后查看. 每一堂课都对应一个学习笔记,下面就开始第一堂课. 这堂课主要是回顾了计算机视觉的起源及其后来 ...
- 回归Qt——写在Qt5.10发布之日
今天偶然看到一条关于Qt5.10发布的消息,发现Qt经历了诺基亚风波之后发展得依然良好,感到很欣慰.回头看上次关注Qt技术还是2011年,那时候用Qt4.7做一个小项目,对于一个写Win32界面和MF ...
- mysql innodb myisam 比较
InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行锁 不支持FULLTEXT类型的索引 不保存表的具体行数,扫描表来计算有多少行 DELETE 表时,是一行一行的删除 InnoDB 把数据和 ...
- php memcache 使用学习
Memcache是什么Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力.它可以应对任 ...
- java 中的 i=i++
记得大学刚开始学C语言时,老师就说:自增有两种形式,分别是i++和++i,i++表示的是先赋值后加1,++i是先加1后赋值,这样理解了很多年也没出现问题,直到遇到如下代码,我才怀疑我的理解是不是错了: ...
- asp.netcore mvc 权限拦截
1-背景介绍 需要做一个简单权限系统,基于 角色,用户,菜单 的模式 基于IActionFilter全局拦截,在内部跳转或者浏览器跳转的时候,拦截是成功的,当通过AJAX 请求的时候,页面就不会跳转 ...
- Python数据挖掘学习路程--起步
一.首先第一步我去了解了Python开发环境:Python(程序运行基础的解释器)+第三方类库(功能扩展)+编辑器(提高代码编辑效率) 编辑器有:Pycharm.Spyder.jupyter note ...
- alpha冲刺(事后诸葛亮)
[设想和目标] Q1:我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? "小葵日记"是为了解决18-30岁年轻用户在记录生活时希望得到一美体验友好 ...
- ORACLE公司传奇历史
ORACLE公司传奇 ORACLE公司之起源 很难想象,ORACLE 公司的这一段传奇居然要从 IBM 公司开始. 1970年的6月,IBM 公司的研究员埃德加·考特 (Edgar Frank Cod ...