zoukankan      html  css  js  c++  java
  • Record of coding:Codeforces 1093E

    E. Intersection of Permutations

    You are given two permutations a and b, both consisting of n elements. Permutation of nn elements is such a integer sequence that each value from 1 to n appears exactly once in it.

    You are asked to perform two types of queries with them:

    • 1 la ra lb rb — calculate the number of values which appear in both segment [la;ra] of positions in permutation aa and segment [lb;rb] of positions in permutation b;
    • 2 x y — swap values on positions x and y in permutation b.

    Print the answer for each query of the first type.

    It is guaranteed that there will be at least one query of the first type in the input.

    Obviously we can use renumeration to make A fixed, and the answer won't be changed. 
    Firstly,let's consider a weak solution.If we use a 2D-BIT to solve this problem, we find the answer is just the sum on rectangle.
    To explain this more intuitively,I use f[i][j] to stand for the sum of number less than or equals to j among the first i numbers of the permutation B.
    Then answer for la,ra,lb and rb equals to  f[ra][rb]-f[la-1][rb]-f[ra][lb-1]+f[la-1][lb-1].This is a simple usage of the principle of inclusion-exclusion.
    In this weak solution, the complexity of time is O((m+n)(logn)^2), but the complexity of memory come up to O(N^2). Considered of the memory limit of 512MB , this solution is completely unacceptable.
    So we must compress the usage of memory.
    My solution is to change each node of the BIT from a BIT into a rb_tree, which consists of all the number fell into this node.
    This action doesn't change the complexity of time but reduce the memory to O(NlogN).
    So this problem is solved.
    Code:
    /**************************************************************************************
     * This code is written by akonoh.                                                    *
     * It can only be compiled by c++17 due to the usage of bits/extc++.h                 *
     * I used pb_ds to reduce the length of my code                                       * 
     * ************************************************************************************/
    #include <bits/stdc++.h>
    #include <bits/extc++.h>
    using namespace std;
    using namespace __gnu_pbds;
    #define N 200*1000
    int n,m;
    tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> tr[N+7],sb;
    inline int lb(int x){return x&-x;}
    void addup(int x,int y)
    {
        for(int i = x; i <= n ; i += lb(i))
        {
            tr[i].insert(y);
        }
    }
    void del(int x, int y)
    {
        for(int i = x; i <= n; i += lb(i))
        {
            tr[i].erase(y);
        }
    }
    int getans(int x, int y)
    {
        int ans = 0;
        for(int i = x; i > 0; i -= lb(i))
        {
            int p = tr[i].order_of_key(y);
            if(*tr[i].lower_bound(y)==y)p++;
            ans += p;
            //this part is to find how many numbers are smaller or equal to y.
        }
        return ans;
    }
    int a[N+8],b[N+8];
    int main()
    {    
        scanf("%d%d",&n,&m);
        for(int i = 1 ; i<= n; i ++)
        {
            int x;
            scanf("%d",&x);
            a[x]=i;
        }
        for(int i = 1; i <= n ;i ++)
        {
            int x;
            scanf("%d",&x);
            b[i]=a[x];//renumeration
        }
        for(int i = 1; i <= n; i ++)
        addup(i,b[i]);
        for(int i = 1; i <= m; i ++)
        {
            int t;
            scanf("%d",&t);
            if(t==1)
            {
                int la,ra,lb,rb,ans=0;
                scanf("%d%d%d%d",&la,&ra,&lb,&rb);
                ans +=getans(rb,ra);
                ans -=getans(lb-1,ra);
                ans -=getans(rb,la-1);
                ans +=getans(lb-1,la-1);
                printf("%d
    ",ans);
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                del(x,b[x]);
                del(y,b[y]);
                swap(b[x],b[y]);
                addup(x,b[x]);
                addup(y,b[y]);
            }
        }
    }
     
     
     
     
  • 相关阅读:
    BZOJ5057 : 区间k小值5
    Urozero Autumn 2016. UKIEPC 2016
    BZOJ2808 : 那些年我们画格子
    BZOJ4970 : [ioi2004]empodia 障碍段
    XVII Open Cup named after E.V. Pankratiev. XXI Ural Championship
    BZOJ4316 : 小C的独立集
    网络流(3)——找到最小st-剪切
    网络流(2)——用Ford-Fullkerson算法寻找最大流
    网络流(1)——网络、流网络和网络流
    退而求其次(4)——椭圆中的最大矩形
  • 原文地址:https://www.cnblogs.com/akonoh/p/10233989.html
Copyright © 2011-2022 走看看