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 }

 

posted @ 2018-12-29 11:16  MJT12044  阅读(187)  评论(0编辑  收藏  举报