CF1093E [Intersection of Permutations]

题意

给定整数n两个1-n的排列a,b,有m次操作:
若opt==1,则有 l1 r1 l2 r2,求出a:[l1,r1]与b:[l2,r2]中相同元素的交的大小。
若opt==2,则有 x y,交换b排列中的 第x位与第y位。

n,m≤200,000



思考

只改变b排序中元素位置,考虑每次询问a中l1-r1的元素何时对答案有贡献。

设a中值为i的位置为pi(下标从1开始),b中值为i的位置为qi,则当且仅当[l1,r1]覆盖pi且[l2,r2]覆盖qi时,对答案有贡献。

再换个角度,若只考虑qi,得满足询问的第二个区间包含了qi

以pi为x轴,qi为y轴建立坐标系,一个询问可以转化为数矩形中有多少个关键点。

那么转换为二维数点。举个例子:

a=[5 1 4 2 3 6]
b=[2 5 3 1 4 6]询问 a:[2,5]与b[3,6],在坐标系中的体现就是:

若图还看不懂,看看每个点的下标,再多想一会儿吧。

这样可持久化线段树维护。注意要内存回收(即有很多答案是0的点,这些点完全没有存在的意义,还占空间,只好把他们给 烤了 回收了)。

O(nlogn2)



代码

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=2E5+5;
  4 int a[maxn],p1[maxn],p2[maxn],where[maxn],x,y,z,n,m;
  5 int bin[maxn],top;
  6 inline int read()
  7 {
  8     int x=0;
  9     static char ch;
 10     ch=getchar();
 11     while(!isdigit(ch))ch=getchar();
 12     while (isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
 13     return x;
 14 }
 15 inline void write(int x)
 16 {
 17     if(x==0)putchar(‘0‘);
 18     int a[10],size=0;
 19     while(x)
 20     {
 21         a[++size]=x%10;
 22         x/=10;
 23     }
 24     for(int i=size;i>=1;--i)putchar(char(a[i]+‘0‘));
 25 }
 26 struct BIT
 27 {
 28     int lowbit(int x){return x&-x;}
 29     int root[maxn],cur;
 30     struct tree{int ls,rs,sum;}t[30000000];
 31     void changeT(int l,int r,int pos,int val,int&num,int pre)
 32     {
 33         if(num==0)
 34         {
 35             if(top>0)num=bin[top--];
 36             else num=++cur;
 37         }
 38         t[num]=t[pre];
 39         t[num].sum+=val;
 40         if(l==r)
 41         {
 42             if(t[num].sum==0)
 43             {
 44                 bin[++top]=num;
 45                 num=0;
 46             }
 47             return;
 48         }
 49         int mid=(l+r)>>1;
 50         if(pos<=mid)changeT(l,mid,pos,val,t[num].ls,t[pre].ls);
 51         else changeT(mid+1,r,pos,val,t[num].rs,t[pre].rs);
 52         if(t[num].rs==0&&t[num].ls==0)
 53         {
 54             bin[++top]=num;
 55             num=0;
 56         }
 57     }
 58     void change(int x,int y,int z)
 59     {
 60         for(int i=x;i<=n;i+=lowbit(i))
 61             changeT(1,n,y,z,root[i],root[i]);
 62     }
 63     int askT(int l,int r,int pos,int num)
 64     {
 65         if(pos==0)return 0;
 66         int mid=(l+r)>>1;
 67         if(r==pos)return t[num].sum;
 68         if(pos<=mid)return askT(l,mid,pos,t[num].ls);
 69         else return t[t[num].ls].sum+askT(mid+1,r,pos,t[num].rs);
 70     }
 71     int ask(int l,int r,int pos)
 72     {
 73         int sum=0;
 74         for(int i=r;i;i-=lowbit(i))
 75             sum+=askT(1,n,pos,root[i]);
 76         for(int i=l-1;i;i-=lowbit(i))
 77             sum-=askT(1,n,pos,root[i]);
 78         return sum;
 79     }
 80 }T;
 81 int main()
 82 {
 83 //    freopen("a.in","r",stdin);
 84 //    freopen("a.out","w",stdout);
 85     n=read();m=read();
 86     for(int i=1;i<=n;++i)
 87     {
 88         p1[i]=read();
 89         where[p1[i]]=i;
 90     }
 91     for(int i=1;i<=n;++i)
 92     {
 93         p2[i]=read();
 94         T.change(i,where[p2[i]],1);
 95     }
 96     for(int i=1;i<=m;++i)
 97     {
 98         int opt,L1,R1,L2,R2;
 99         opt=read();
100         if(opt==2)
101         {
102             x=read();y=read();
103             T.change(x,where[p2[x]],-1);
104             T.change(y,where[p2[y]],-1);
105             swap(p2[x],p2[y]);
106             T.change(x,where[p2[x]],1);
107             T.change(y,where[p2[y]],1);
108         }
109         else
110         {
111             L1=read();R1=read();L2=read();R2=read();
112             if(L1>R1)swap(L1,R1);
113             if(L2>R2)swap(L2,R2);
114             write(T.ask(L2,R2,R1)-T.ask(L2,R2,L1-1));
115             putchar(‘\n‘);
116         }
117     }
118     return 0;
119 }

原文地址:https://www.cnblogs.com/GreenDuck/p/10585654.html

时间: 2024-10-22 02:53:14

CF1093E [Intersection of Permutations]的相关文章

【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\) 下

[树状数组][权值线段树] Codeforces 1093E Intersection of Permutations

题目描述 You are given two permutations aa and bb , both consisting of nn elements. Permutation of nn elements is such a integer sequence that each value from 11 to nn appears exactly once in it. You are asked to perform two types of queries with them: 1

CF1093:E. Intersection of Permutations(树状数组套主席树)

题意:给定长度为N的a数组,和b数组,a和b都是1到N的排列: 有两种操作,一种是询问[L1,R1],[L2,R2]:即问a数组的[L1,R1]区间和b数组的[L2,R2]区间出现了多少个相同的数字. 一种是修改b数组两个位置的值. 思路:如果把b数组每个数取对应a数组对应数的位置,即按照b的下标建立横坐标,纵坐标是它在a中的位置,那么问题就成了,询问在区间[L2,R2]里面,多少个数在[L1,R1]这区间.  这很明显就是主席树可以解决的了.时间复杂度是O(N*logN*logN):常数差不多

Cideforces 1093E Intersection of Permutations (CDQ分治+树状数组)

---恢复内容开始--- 题意:给你两个数组a和b,a,b都是一个n的全排列:有两种操作:一种是询问区间在数组a的区间[l1,r1]和数组b的区间[l2,r2]出现了多少相同的数字,另一种是交换数组b中x位置和y位置的数字. 思路:我们可以建立数组b对数组a的映射mp,mp[x]表示数组b中x位置的数在数组a中出现的位置,这样问题转化为了带修改的询问一个矩形内点的个数的问题.想法是树套树,但是这题卡常,很多树套树会被卡掉,介于本辣鸡的代码能力,很容易写丑,所以用CDQ分治. 此问题和三维偏序问题

Record of coding:Codeforces 1093E

E. Intersection of Permutations You are given two permutations a and b, both consisting of n elements. Permutation of nn elements is such a integer sequence that each value from 1 to n appears exactly once in it. You are asked to perform two types of

Educational Codeforces Round 56 Editorial

A.Dice Rolling 题意:Mishka 有一个六面的骰子,每面分别为 2 ~ 7,而且 Mishka 是欧皇,可以控制自己每次掷到的数字.Mishka 现在想掷若干次骰子,使得掷到的点数总和为 x,请求出任意一种掷骰子的方案,并输出掷骰子的次数.由于 Mishka 很好奇不同数字的方案,所以有 t 组询问. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=3e5+10

[LeetCode] 349 Intersection of Two Arrays &amp; 350 Intersection of Two Arrays II

这两道题都是求两个数组之间的重复元素,因此把它们放在一起. 原题地址: 349 Intersection of Two Arrays :https://leetcode.com/problems/intersection-of-two-arrays/description/ 350 Intersection of Two Arrays II:https://leetcode.com/problems/intersection-of-two-arrays-ii/description/ 题目&解法

spark 教程三 spark Map filter flatMap union distinct intersection操作

RDD的创建 spark 所有的操作都围绕着弹性分布式数据集(RDD)进行,这是一个有容错机制的并可以被并行操作的元素集合,具有只读.分区.容错.高效.无需物化.可以缓存.RDD依赖等特征 RDD的创建基础RDD 1.并行集合(Parallelized Collections):接收一个已经存在的Scala集合,然后进行各种并行运算 var sc=new SparkContext(conf) var rdd=sc.parallelize(Array(2,4,9,3,5,7,8,1,6)); rd

350.求两个数组的交集 Intersection of Two Arrays II

Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2]. Note: Each element in the result should appear as many times as it shows in both arrays. The result can be in any ord