[题解]CF1093E Intersection of Permutations

CF1093E

翻译很清晰,就不再重复题意了。

\(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;
}
posted @ 2020-12-26 09:41  watermonster1y1  阅读(64)  评论(0编辑  收藏  举报