1. 程式人生 > >CF 1093E Intersection of Permutations——CDQ分治

CF 1093E Intersection of Permutations——CDQ分治

題目:http://codeforces.com/contest/1093/problem/E

只能想到轉化成查詢一個區間裡值在一個範圍裡的數的個數……

沒有想到這樣適合用主席樹套樹狀陣列維護。不過據說卡空間。

參考了這裡的題解:https://www.luogu.org/problemnew/solution/CF1093E

寫了CDQ分治。一個值在兩個序列裡的位置看成兩維座標的話,就是查平面區域內點的個數。

按 x (在第一個序列裡的位置)排序,分治操作的時間,y (在第二個序列裡的位置)用樹狀陣列解決。

做這一層的時候要先列舉,再消除影響,然後再把 a[ ] 分成兩部分。這樣才能保證貢獻給這個詢問的是 x 在它之前、時間在它之前的那些 y 。在樹狀數組裡就不考慮 x 了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+5;
int n,m,ta[N],tb[N],pa[N],pb[N],ans[N],tot,f[N],cnt;
struct Node
{
  bool fx;int x,y,k,id,tim;
  Node(bool f=0,int x=0,int y=0,int k=0,int i=0,int t=0):
    fx(f),x(x),y(y),k(k),id(i),tim(t) {}
  
bool operator< (const Node &b)const {return x<b.x||(x==b.x&&tim<b.tim);} }a[(N<<2)+N],b[(N<<2)+N];//+N int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0'
,ch=getchar(); return fx?ret:-ret; } void add(int x,int k){for(;x<=n;x+=(x&-x))f[x]+=k;} int query(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;} void solve(int l,int r) { if(l>=r)return; int mid=l+r>>1,p0=l,p1=mid+1; for(int i=l;i<=r;i++) if(!a[i].fx&&a[i].tim<=mid)add(a[i].y,a[i].k); else if(a[i].fx&&a[i].tim>mid)ans[a[i].id]+=a[i].k*query(a[i].y); for(int i=l;i<=r;i++) if(!a[i].fx&&a[i].tim<=mid)add(a[i].y,-a[i].k); for(int i=l;i<=r;i++) if(a[i].tim<=mid)b[p0++]=a[i]; else b[p1++]=a[i]; for(int i=l;i<=r;i++)a[i]=b[i]; solve(l,mid); solve(mid+1,r); } int main() { n=rdn();m=rdn(); for(int i=1;i<=n;i++)ta[i]=rdn(),pa[ta[i]]=i; for(int i=1;i<=n;i++)tb[i]=rdn(),pb[tb[i]]=i; for(int i=1;i<=n;i++) a[++cnt]=Node(0,pa[i],pb[i],1,0,cnt);//1 for(int i=1,op,x1,y1,x2,y2,w1,w2;i<=m;i++) { op=rdn(); if(op==1) { tot++; x1=rdn();x2=rdn();y1=rdn();y2=rdn(); x1--; y1--; a[++cnt]=Node(1,x2,y2,1,tot,cnt); a[++cnt]=Node(1,x1,y2,-1,tot,cnt); a[++cnt]=Node(1,x2,y1,-1,tot,cnt); a[++cnt]=Node(1,x1,y1,1,tot,cnt); } else { int w1=rdn(),w2=rdn(); y1=w1;x1=pa[tb[w1]];y2=w2;x2=pa[tb[w2]]; swap(pb[tb[w1]],pb[tb[w1]]); swap(tb[w1],tb[w2]); a[++cnt]=Node(0,x1,y1,-1,0,cnt); a[++cnt]=Node(0,x2,y2,-1,0,cnt); a[++cnt]=Node(0,x1,y2,1,0,cnt); a[++cnt]=Node(0,x2,y1,1,0,cnt); } } sort(a+1,a+cnt+1); solve(1,cnt); for(int i=1;i<=tot;i++)printf("%d\n",ans[i]); return 0; }