題意
給定整數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 }