zoukankan      html  css  js  c++  java
  • 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
    ", ans[i]);
    100     return 0;
    101 }
  • 相关阅读:
    java之设计模式
    java关键字volatile用法详解
    java关键字tranisent用法详解
    java关键字final用法详解
    java关键字static用法详解
    护眼纯黑色VS2012配色方案
    (正能量)进击的菜鸟
    13、python实现罗马数字转整数
    python判断回文数-leetcode算法
    正确显示中文标签和正负号
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10194738.html
Copyright © 2011-2022 走看看