「Two permutations」Solution

文章讨论了一个关于两个给定排列的查询问题,需要找出满足特定条件的数。通过构建主席树结构,实现在线处理查询,有效地解决了空间限制。代码展示了如何使用段树进行特定区间值域的查询操作。
摘要由CSDN通过智能技术生成

简述题意

给定两个长度为 n n n 的排列 a , b a,b a,b,以及 q q q 次询问,每次询问给定 l 1 , r 1 , l 2 , r 2 l_1,r_1,l_2,r_2 l1,r1,l2,r2,求出有多少个数 x x x 满足 x ∈ a i , i ∈ [ l 1 , r 1 ] x\in{a_{i}},i\in[l_1,r_1] xai,i[l1,r1] x ∈ b i , i ∈ [ l 2 , r 2 ] x \in b_i, i \in[l_2,r_2] xbi,i[l2,r2],强制在线。

思路

这种板子题评紫

注意到每个数仅出现一次,所以不妨令 a i a_i ai b b b 排列中出现的位置为 t o i to_i toi,每次查询 [ l 1 , r 1 ] [l_1,r_1] [l1,r1] 中有多少个 t o i to_i toi 满足 l 2 ≤ t o i ≤ r 2 l_2 \le to_i \le r_2 l2toir2 即可。特定区间值域查询,一眼主席树。

代码

注意这道题有点卡空间,不要乱开。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1.2e6 + 5;
int n , m , a[MAXN] , b[MAXN] , lastans = -1;
namespace Segement{
	static int tot , rt[MAXN] , root;
	struct tree{
		int l , r , sum , ls , rs;
	}tree[MAXN * 20];
	int build(int p , int l , int r) {
		p = ++ tot;
		tree[p].l = l , tree[p].r = r;
		if (l == r) return p;
		int mid = l + r >> 1;
		tree[p].ls = build(p , l , mid) , tree[p].rs = build(p , mid + 1 , r);
		return p;
	}
	int newnode(int p) {
		tree[++ tot] = tree[p];
		return tot;
	}
	int update(int p , int x) {
		int now = newnode(p);
		tree[now].sum ++;
		if (tree[now].l == tree[now].r) return now;
		int mid = tree[now].l + tree[p].r >> 1;
		if (x <= mid) tree[now].ls = update(tree[now].ls , x);
		else tree[now].rs = update(tree[now].rs , x);
		return now;
	}
	int query(int p , int p2 , int l , int r) {
		if (tree[p].l >= l && tree[p].r <= r) return tree[p2].sum - tree[p].sum;
		int mid = tree[p].l + tree[p].r >> 1 , tmp = 0;
		if (l <= mid) tmp += query(tree[p].ls , tree[p2].ls , l , r);
		if (r > mid) tmp += query(tree[p].rs , tree[p2].rs , l , r);
		return tmp;
	}
}
using namespace Segement;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr) , cout.tie(nullptr);
	cin >> n;
	for (int i = 1 ; i <= n ; i ++) cin >> a[i];
	for (int i = 1 , x ; i <= n ; i ++) cin >> x , b[x] = i;
	rt[0] = build(1 , 1 , n);
	for (int i = 1 ; i <= n ; i ++) rt[i] = update(rt[i - 1] , b[a[i]]);
	cin >> m;
	while(m --) {
		int a , b , c , d;
		cin >> a >> b >> c >> d;
		int l1 = (a + lastans) % n + 1 , r1 = (b + lastans) % n + 1;
		int l2 = (c + lastans) % n + 1 , r2 = (d + lastans) % n + 1;
		if (l1 > r1) swap(l1 , r1);
		if (l2 > r2) swap(l2 , r2);
		cout << (lastans = query(rt[l1 - 1] , rt[r1] , l2 , r2)) << '\n';
	}
	return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值