CF 1093 E. Intersection of Permutations
E. Intersection of Permutations
题意:
给定两个序列,询问第一个排列的[l1,r1]和第二个排列[l2,r2]中有多少个共同的数,支持在第二个排列中交换两个数。
分析:
首先求出一个数组,c[i],第二个排列的这个数字在第一个排列中出现的位置。那么查询就是询问c数组中的[l2,r2]中的有多少个数字的在[l1,r1]之间。此时可以差分+离线+树状数组在$nlogn$的时间复杂度内完成。
考虑修改操作,考虑cdq分治。在b排列中交换两个数,那么也就是c数组中交换这两个数,可以拆成一个加入和删除的操作。然后cdq分治,时间复杂度$nlog^2n$。
这道题也有树套树,分块的作法。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<cctype> 7 #include<set> 8 #include<queue> 9 #include<vector> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 14 inline int read() { 15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 17 } 18 19 const int N = 200005; 20 21 struct Node{ 22 int flag, l, r, pos, id, v; 23 }A[N * 7], B[N * 7]; 24 int pos[N], a[N], b[N], ans[N]; 25 26 27 struct BIT{ 28 int sum[N], n; 29 void update(int p,int v) { 30 for (; p <= n; p += (p & (-p))) sum[p] += v; 31 } 32 int query(int p) { 33 int ans = 0; 34 for (; p; p -= (p & (-p))) ans += sum[p]; 35 return ans; 36 } 37 int Ask(int l,int r) { 38 return query(r) - query(l - 1); 39 } 40 }bit; 41 42 void cdq(int l,int r) { 43 if (l >= r) return ; 44 int mid = (l + r) >> 1; 45 cdq(l, mid); 46 cdq(mid + 1, r); 47 48 int i = l, j = mid + 1, k = l; 49 while (i <= mid && j <= r) { 50 if (A[i].pos <= A[j].pos) { 51 if (A[i].flag != 2) bit.update(A[i].v, A[i].flag); 52 B[k ++] = A[i ++]; 53 } 54 else { 55 if (A[j].flag == 2) ans[A[j].id] += bit.Ask(A[j].l, A[j].r) * A[j].v; 56 B[k ++] = A[j ++]; 57 } 58 } 59 while (j <= r) { 60 if (A[j].flag == 2) ans[A[j].id] += bit.Ask(A[j].l, A[j].r) * A[j].v; 61 B[k ++] = A[j ++]; 62 } 63 for (int t = l; t < i; ++t) if (A[t].flag != 2) bit.update(A[t].v, -A[t].flag); 64 while (i <= mid) B[k ++] = A[i ++]; 65 for (int t = l; t <= r; ++t) A[t] = B[t]; 66 } 67 68 int main() { 69 int n = read(), m = read(); bit.n = n; 70 for (int i = 1; i <= n; ++i) { 71 a[i] = read(); 72 pos[a[i]] = i; 73 } 74 for (int i = 1; i <= n; ++i) { 75 b[i] = read(); 76 } 77 int cnt = 0, tot = 0; 78 for (int i = 1; i <= n; ++i) { 79 A[++cnt] = (Node){1, 0, 0, i, 0, pos[b[i]]}; 80 } 81 for (int i = 1; i <= m; ++i) { 82 int opt = read(); 83 if (opt == 1) { 84 int l1 = read(), r1 = read(), l2 = read(), r2 = read(); 85 ++tot; 86 ++cnt; A[cnt] = (Node){2, l1, r1, l2 - 1, tot, -1}; 87 ++cnt; A[cnt] = (Node){2, l1, r1, r2, tot, 1}; 88 } 89 else { 90 int x = read(), y = read(); 91 ++cnt; A[cnt] = (Node){-1, 0, 0, x, 0, pos[b[x]]}; 92 ++cnt; A[cnt] = (Node){-1, 0, 0, y, 0, pos[b[y]]}; 93 swap(b[x], b[y]); 94 ++cnt; A[cnt] = (Node){1, 0, 0, x, 0, pos[b[x]]}; 95 ++cnt; A[cnt] = (Node){1, 0, 0, y, 0, pos[b[y]]}; 96 } 97 } 98 cdq(1, cnt); 99 for (int i = 1; i <= tot; ++i) printf("%d\n", ans[i]); 100 return 0; 101 }