[题解]CF1093E Intersection of Permutations
翻译很清晰,就不再重复题意了。
\(a\) 和 \(b\) 都是 \(1\) 到 \(n\) 的一个排列,所以我们可以记$ A_i$ 为 \(i\) 在 \(a\) 中的位置, \(B_i\) 为 \(i\) 在 \(b\) 中的位置,每次询问就是求有多少个 \(i\) 满足 \(la \le A_i \le ra\) 且 \(lb \le B_i \le rb\) 。那么问题就变为一个很裸的二维数点了,直接用树状数组来维护\(A\),套线段树维护\(B\)可以很轻松地解决这个问题。
由于题目修改操作只要求了交换两个数在 \(b\) 排列中的位置,我们可以先在两个数原来的位置 \(-1\) ,交换 \(B\) 的值再在新的位置 \(+1\) 。
注意修改操作很多,会产生大量无用节点,一定要回收!!(不然会RE/MLE)
代码(部分细节有出入):
#include <cstdio>
using namespace std;
#define il inline
#define re register
const int N=2e5+10;
namespace FastIO
{
char buf[1<<21],buf2[1<<21],*p1=buf,*p2=buf;
int p,p3=-1;
il int getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
il void flush(){fwrite(buf2,1,p3+1,stdout),p3=-1;}
#define isdigit(ch) (ch>=48&&ch<=57)
template <typename T>
il void read(T &x)
{
re bool f=0;x=0;
re char ch=getc();
while(!isdigit(ch)) f|=(ch=='-'),ch=getc();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getc();
x=f?-x:x;
}
template <typename T>
il void print(T x)
{
if(p3>(1<<20)) flush();
if(x<0) buf2[++p3]=45,x=-x;
re int a[50]={};
do{a[++p]=x%10+48;}while(x/=10);
do{buf2[++p3]=a[p];}while(--p);
buf2[++p3]='\n';
}
}
using namespace FastIO;
//IO优化
il void swap(int &a,int &b){a^=b^=a^=b;return;}
int rt[N],pool;
int bin[N<<7],top;
//废弃节点回收
il int newnode(){return top?bin[top--]:++pool;}
int ls[N<<7],rs[N<<7];
int cnt[N<<7];
il void deletnode(int &p){bin[++top]=p;p=0;return;}
il void insert(int &p,int l,int r,int pos,int x)
{
if(!p) p=newnode();
cnt[p]+=x;
if(l==r) return;
re int mid=(l+r)>>1;
if(pos>mid) insert(rs[p],mid+1,r,pos,x);
else insert(ls[p],l,mid,pos,x);
if(!cnt[p]) deletnode(p);
return;
}
il int query(int p,int l,int r,int L,int R)
{
if(!p||l>R||r<L) return 0;
if(l>=L&&r<=R) return cnt[p];
re int mid=(l+r)>>1;
return query(ls[p],l,mid,L,R)+query(rs[p],mid+1,r,L,R);
}
int n,m;
int a[N],b[N],B[N];
#define lowbit(x) (x&-x)
il void add(int x,int y,int z)
{
for(re int i=x;i<=n;i+=lowbit(i))
insert(rt[i],1,n,y,z);
return;
}
il int ask(int xa,int xb,int ya,int yb)
{
re int res=0;
for(re int i=xb;i;i-=lowbit(i))
res+=query(rt[i],1,n,ya,yb);
for(re int i=xa-1;i;i-=lowbit(i))
res-=query(rt[i],1,n,ya,yb);
//减掉多加的
return res;
}
il void Swap(int x,int y)
{
add(a[B[x]],b[B[x]],-1);add(a[B[y]],b[B[y]],-1);
//减掉原来的
swap(B[x],B[y]);b[B[x]]=x;b[B[y]]=y;
add(a[B[x]],b[B[x]],1);add(a[B[y]],b[B[y]],1);
//加上新的
return;
}
int main()
{
read(n);read(m);
for(re int i=1,x;i<=n;++i) read(x),a[x]=i;
for(re int i=1;i<=n;++i) read(B[i]),b[B[i]]=i;
for(re int i=1;i<=n;++i) add(a[i],b[i],1);
re int opt,x,y,la,ra,lb,rb;
while(m--)
{
read(opt);
if(opt==1) read(la),read(ra),read(lb),read(rb),print(ask(la,ra,lb,rb));
else read(x),read(y),Swap(x,y);
}
flush();return 0;
}