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


    (color{#0066ff}{ 题目描述 })

    给定整数 (n) 和两个 (1,dots,n) 的排列 (a,b)

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

    • (1 l_a r_a l_b r_b),设 (a)([l_a;r_a]) 区间内的元素集合为 (S_a),设 (b)([l_b;r_b]) 区间内的元素集合为 (S_b),求 (lvert S_a igcap S_b vert)
    • (2 x y),交换 (b) 的第 (x) 位与第 (y) 位。

    (1 le n,m le 2 cdot 10^5)

    (color{#0066ff}{输入格式})

    第一行,两个整数 (n,m) 以下两行,每行 (n) 个整数,分别表示 (a,b)。 以下 (m) 行,每行一个操作。

    (color{#0066ff}{输出格式})

    对于每个 (1) 操作,输出答案。

    (color{#0066ff}{输入样例})

    6 7
    5 1 4 2 3 6
    2 5 3 1 4 6
    1 1 2 4 5
    2 2 4
    1 1 2 4 5
    1 2 3 3 5
    1 1 6 1 2
    2 4 1
    1 4 4 1 3
    

    (color{#0066ff}{输出样例})

    1
    1
    1
    2
    0
    

    (color{#0066ff}{数据范围与提示})

    (2leq n leq 2*10^5, 1leq m leq 2*10^5)

    (color{#0066ff}{ 题解 })

    对于排列的每个元素,都有在a中出现的位置pa,在b中出现的位置pb

    将其当做二维点(pa,pb),那么其实这题就建好模了

    给你二维平面上的一些点

    有交换两个点的y坐标操作

    每次查询一个矩形内有多少点

    树套树

    树状数组套权值线段树

    树状数组维护pb, 权值线段树维护对应区间的pa

    在权值线段树上找到对应区间返回

    要写数组版,而且还得内存回收,作为指针选手,以哭晕qwq

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; int x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 1e6 * 40;
    const int N = 2e5 + 10;
    struct node {
    	int num;
    	int ch[2];
    	int &operator [] (const int &b) {
    		return ch[b];
    	}
    	node(int a = 0): num(a) {
    		ch[0] = ch[1] = 0;
    	}
    }e[maxn];
    int a[N], b[N], pa[N], pd[N], cnt;
    int root[N];
    int n, m;
    int sta[N], top;
    int low(int x) { return (x) & (-x); }
    int newnode() {
    	return top? sta[top--] : ++cnt;
    }
    void add(int &now, int pos, int k, int l, int r) {
    	if(!now) now = newnode();
    	e[now].num += k;
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	if(pos <= mid) add(e[now][0], pos, k, l, mid);
    	else add(e[now][1], pos, k, mid + 1, r);
    	if(!e[now].num) sta[++top] = now, now = 0;
    }
    void add(int pos, int val, int k) {
    	for(int i = pos; i <= n; i += low(i))
    		add(root[i], val, k, 1, n);
    }
    int query(int L, int R, int now, int l, int r) {
    	if(!now) return 0;
    	if(L <= l && r <= R) return e[now].num;
    	int mid = (l + r) >> 1, tot = 0;
    	if(L <= mid) tot += query(L, R, e[now][0], l, mid);
    	if(R > mid) tot += query(L, R, e[now][1], mid + 1, r);
    	return tot;
    }
    int query(int L, int R, int l, int r) {
    	int ans = 0;
    	for(int i = L - 1; i; i -= low(i)) ans -= query(l, r, root[i], 1, n);
    	for(int i = R; i; i -= low(i)) ans += query(l, r, root[i], 1, n);
    	return ans;
    }
    int main() {
    	n = in(), m = in();
    	for(int i = 1; i <= n; i++) a[i] = in(), pa[a[i]] = i;
    	for(int i = 1; i <= n; i++) b[i] = pa[in()];
    	for(int i = 1; i <= n; i++) add(i, b[i], 1);
    	int flag, l, r, L, R;
    	while(m --> 0) {
    		flag = in();
    		if(flag == 1) {
    			L = in(), R = in(), l = in(), r = in();
    			printf("%d
    ", query(l, r, L, R));
    		}
    		else {
    			l = in(), r = in();
    			add(l, b[l], -1);
    			add(r, b[r], -1);
    			add(l, b[r], 1);
    			add(r, b[l], 1);
    			std::swap(b[l], b[r]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Express本地测试HTTPS
    在 WebStorm 中,配置能够识别 Vue CLI 3 创建的项目的别名 alias
    在线版本的ps
    功能强大的任务日历组件
    tree-shaking实战
    深入diff 算法
    【题解】[SHOI2001] Panda 的烦恼
    【题解】[JLOI2011]不重复数字
    「Codeforces Global Round #10」赛后个人总结
    【题解】[SCOI2004] 文本的输入
  • 原文地址:https://www.cnblogs.com/olinr/p/10227230.html
Copyright © 2020-2023  润新知