题意不说了 学了个新姿势:对于每个值 记录他们在a序列和b序列中的位置 假设我们以b的位置为x轴 a的位置为y轴 那么询问 就变成了 在 矩阵 左下角(lb,la) 右上角(rb,ra)内有几个点
显然是cdq裸题 关键在上述转换 树套树也是同样的思路 但是比cdq慢很多
cdq代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
int n,m,tot;
struct Query{
int type,x,y,flag,id,cnt;
bool operator < (const Query &b)const{
if(x==b.x) return type<b.type;
else return x<b.x;
}
}q[N*20],temp[N*20];
int a[N],b[N],mp[N],pos[N],ans[N],c[N];
void add(int x,int val){
while(x<N){
if(x==0) break;
c[x]+=val;
x+=x&-x;
}
}
int query(int x){
int ret = 0;
while(x){
ret+=c[x];
x-=x&-x;
}return ret;
}
void del(int x){
while(x<N){
if(x==0) break;
c[x]=0;
x+=x&-x;
}
}
void cdq(int L,int R){
if(L==R) return;
int M = L+R>>1;
cdq(L,M);cdq(M+1,R);
int l = L,r = M+1,cnt = L;
for(;r<=R;r++){
while(l<=M&&q[l]<q[r]){
if(q[l].type==0)
add(q[l].y,q[l].cnt);
temp[cnt++]=q[l++];
}
if(q[r].type==1) ans[q[r].id]+=q[r].flag*query(q[r].y);
temp[cnt++]=q[r];
}
for(int i = l; i <= M; i++) temp[cnt++]=q[i];
for(int i = L; i < l; i++)
if(q[i].type==0) del(q[i].y);
for(int i = L; i <= R; i++)
q[i]=temp[i];
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]),pos[a[i]]=i;
for(int i = 1; i <= n; i++){
scanf("%d",&b[i]);
mp[i]=pos[b[i]];
q[++tot]=(Query){0,i,mp[i],0,0,1};
}
int op,qt=0;
for(int i = 1; i <= m; i++){
scanf("%d",&op);
if(op==1){
int l1,l2,r1,r2;
scanf("%d%d%d%d",&l2,&r2,&l1,&r1);
q[++tot]=(Query){1,l1-1,l2-1,1,++qt,0};
q[++tot]=(Query){1,r1,l2-1,-1,qt,0};
q[++tot]=(Query){1,l1-1,r2,-1,qt,0};
q[++tot]=(Query){1,r1,r2,1,qt,0};
}else{
int x,y;
scanf("%d%d",&x,&y);
q[++tot]=(Query){0,x,mp[x],0,0,-1};
q[++tot]=(Query){0,y,mp[y],0,0,-1};
swap(mp[x],mp[y]);
q[++tot]=(Query){0,x,mp[x],0,0,1};
q[++tot]=(Query){0,y,mp[y],0,0,1};
}
}
cdq(1,tot);
for(int i = 1; i <= qt; i++) printf("%d\n",ans[i]);
return 0;
}
树套树代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
const int M = N*50;
int n,m,a[N],pos[N],root[N],top,st[N],cnt,b[N];
struct node{int num,ch[2];}e[M];
void update(int &o,int l,int r,int pos,int val){
if(!o) o=top?st[top--]:++cnt;
e[o].num+=val;
int mid = l+r>>1;
if(l==r) return;
if(pos<=mid) update(e[o].ch[0],l,mid,pos,val);
else update(e[o].ch[1],mid+1,r,pos,val);
if(e[o].num==0) st[++top]=o,o=0;
}
int query(int o,int l,int r,int L,int R){
if(!o) return 0;
if(L<=l&&R>=r) return e[o].num;
int mid = l+r>>1,ans=0;
if(L<=mid) ans+=query(e[o].ch[0],l,mid,L,R);
if(R>mid) ans+=query(e[o].ch[1],mid+1,r,L,R);
return ans;
}
void add(int x,int y,int v){
for(int i = x; i <= n; i+=i&-i) update(root[i],1,n,y,v);
}
int que(int L,int R,int l,int r){
int ans = 0;
for(int i = L-1; i; i-=i&-i) ans-=query(root[i],1,n,l,r);
for(int i = R; i; i-=i&-i) ans+=query(root[i],1,n,l,r);
return ans;
}
int main(){
scanf("%d%d",&n,&m);
int x;
for(int i = 1; i <= n; i++) scanf("%d",&a[i]),pos[a[i]]=i;
for(int i = 1; i <= n; i++) scanf("%d",&x),b[i]=pos[x];
for(int i = 1; i <= n; i++) add(i,b[i],1);
for(int i = 1; i <= m; i++){
int op;
scanf("%d",&op);
if(op==1){
int l,r,L,R;
scanf("%d%d%d%d",&l,&r,&L,&R);
printf("%d\n",que(L,R,l,r));
}else{
int x,y;
scanf("%d%d",&x,&y);
add(x,b[x],-1),add(y,b[y],-1);
swap(b[x],b[y]);
add(x,b[x],1),add(y,b[y],1);
}
}
return 0;
}