codeforce1093E Intersection of Permutations 树状数组+分块

E. Intersection of Permutations

time limit per test6 seconds

memory limit per test512 megabytes

inputstandard input

outputstandard output

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 la ra lb rb1 la ra lb rb — calculate the number of values which appear in both segment [la;ra][la;ra] of positions in permutation aa and segment [lb;rb][lb;rb] of positions in permutation bb;

2 x y2 x y — swap values on positions xx and yy in permutation bb.

Print the answer for each query of the first type.

It is guaranteed that there will be at least one query of the first type in the input.

Input

The first line contains two integers nn and mm (2≤n≤2⋅1052≤n≤2⋅105, 1≤m≤2⋅1051≤m≤2⋅105) — the number of elements in both permutations and the number of queries.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤n1≤ai≤n) — permutation aa. It is guaranteed that each value from 11 to nn appears in aa exactly once.

The third line contains nn integers b1,b2,…,bnb1,b2,…,bn (1≤bi≤n1≤bi≤n) — permutation bb. It is guaranteed that each value from 11 to nn appears in bb exactly once.

Each of the next mm lines contains the description of a certain query. These are either:

1 la ra lb rb1 la ra lb rb (1≤la≤ra≤n1≤la≤ra≤n, 1≤lb≤rb≤n1≤lb≤rb≤n);

2 x y2 x y (1≤x,y≤n1≤x,y≤n, x≠yx≠y).

Output

Print the answers for the queries of the first type, each answer in the new line — the number of values which appear in both segment [la;ra][la;ra] of positions in permutation aa and segment [lb;rb][lb;rb] of positions in permutation bb.

Example

inputCopy

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

outputCopy

1

1

1

2

0

题目大意:给两个排列A,B,两种操作:1.询问A序列区间[a,b]和B序列区间[c,d]有多少个相同的数字 2.调换序列B第x和第y个元素

    考虑增加一个序列C,C[i]表示B第i个位置的元素在A中的位置,这样询问A,B在区间[a,b],[c,d]有多少个相同元素时,即询问序列C在[c,d]有多少个元素的范围[a,b]之间,加上修改操作。。。

        

        分块+树状数组。。将序列分为√n块,先试对每一块都用一个树状树组来维护这一块的信息,用个T[√n][n]大小的二维数组来维护,即第i个树状数组维护的是第i块元素的信息,这样查询区间[1,i]有多少个元素小于x时,就可先对i所在块暴力统计一下,再跑√n次对前面每一块用树状数组去统计,但这样每次查询的时间复杂度为√nlogn,是过不了的鸭!!

        对i所在块还是要暴力一下,前面的块由于要跑√n次,可以考虑用树状数组来对块改进操作,即T[i][N]维护的是第i-lowbit(i)块到第i块的信息,然后就可以从跑√n次减到log(√n)次辣!所以总的时间复杂度在 n(logn)(log√n)到n√n之间,还是会比n(logn)^2的树套树快一点的。

        用主席树套树状数组的话要加个队列记录用过的结点,不然直接开n(logn)^2的空间会直接爆掉512M限制的。

        代码

#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
int A[200010],B[200010],n,T[500][200010],q;
int lowbit(int x){
    return x&-x;
}
void add(int x,int k,int v){
     x=x/q+1;
     int i;
     for(;x<=n/q;x+=lowbit(x)){
        for(i=k;i<=n;i+=lowbit(i)) T[x][i]+=v;
     }
}
int sum(int x,int k){
    int y=x/q*q,ans=0,i;
    if(!y) y=1;
    for(i=y;i<=x;i++) if(B[i]<=k) ans++;
    x=x/q;
    for(;x;x-=lowbit(x)){
        for(i=k;i;i-=lowbit(i)) ans+=T[x][i];
    }
    return ans;
}

int main(){
    int i,m,x;
    scanf("%d%d",&n,&m);
    q=sqrt(n);
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        A[x]=i;
    }
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        B[i]=A[x];
    }
    for(i=1;i<=n;i++) add(i,B[i],1);
    int a,b,c,d,e,ans;
    while(m--){
        scanf("%d",&a);
        if(a==1){
            scanf("%d%d%d%d",&b,&c,&d,&e);
            ans=sum(e,c)-sum(e,b-1)-sum(d-1,c)+sum(d-1,b-1);
            printf("%d\n",ans);
        }
        else{
            scanf("%d%d",&b,&c);
            add(b,B[b],-1);
            add(c,B[c],-1);
            add(b,B[c],1);
            add(c,B[b],1);
            swap(B[b],B[c]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/guogai13/article/details/85043263