• 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;
    }
    
  • 相关阅读:
    HDU 1114 Piggy-Bank
    HDU 2955 Robberies
    NTOJ 290 动物统计(加强版)
    POJ 3624 Charm Bracelet
    HDU 2602 Bone Collector
    POJ 1523 SPF(无向图割顶)
    HDU 5311 Hidden String
    HDU 1421 搬寝室
    HDU 1058 Humble Numbers
    POJ 3259 Wormholes(spfa判负环)
  • 原文地址:https://www.cnblogs.com/olinr/p/10227230.html
Copyright © 2020-2023  润新知