zoukankan      html  css  js  c++  java
  • Day6

    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删
    除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数
    Input
    输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
    以下n行每行包含一个1到n之间的正整数,即初始排列。
    以下m行每行一个正整数,依次为每次删除的元素。
    N<=100000 M<=50000
    Output
     
    输出包含m行,依次为删除每个元素之前,逆序对的个数。
    Sample Input5 4 1 5 3 4 2 5 1 4 2

    Sample Output5 2 2 1 样例解释 (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

    思路:逆序对删除可以看作是三维偏序问题,三元组<pos,val,time>,排序定一序,分治定一序,一维直接树状数组维护求和即可

    满足逆序对有2种情况:

    1.pos0>pos, val0<val, time0<time

    2.pos0<pos, val0>val, time0<time

    可以在读入时定pos的序,就是求每个点左边值大于这个点的和右边值小于这个点的关于时间的偏序,时间都要大于这个点

    在分治时,保证两个区间的pos是有序的,但区间内不保证,因为他们是val序,所以左右区间一个查询一个修改,就能保证pos序了

    这样,在分治时分别统计两次即可,注意每次都要清空影响,最后直接用sort排序即可,因为时间大于这个点,所以统计的数量是sum(m+1)-sum(time0)

    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    
    const int maxm = 1e5+10;
    
    int C[maxm], n, m, ans[maxm], Cache[maxm];
    
    void add(int x, int val) {
        for(; x <= n+1; x += lowbit(x))
            C[x] += val;
    }
    
    int getsum(int x) {
        int ret = 0;
        for(; x; x -= lowbit(x))
            ret += C[x];
        return ret;
    }
    
    struct Node {
        int val, tim, ans;
    } buf[maxm], res[maxm];
    
    bool cmpval(Node a, Node b) {
        return a.val < b.val;
    }
    
    void CDQ(int L, int R) {
        if(L == R) return;
        int mid = (L+R) >> 1;
        CDQ(L, mid), CDQ(mid+1, R);
        int i = L, j = mid+1;
        // 计算右边小于他的
        while(i <= mid && j <= R) {
            if(res[i].val > res[j].val)
                add(res[j++].tim, 1);
            else 
                res[i].ans += getsum(m+1)-getsum(res[i++].tim);
        }
        while(i <= mid)
            res[i].ans += getsum(m+1)-getsum(res[i++].tim);
        // 清除数组
        for(int l = mid+1; l < j; ++l)
            add(res[l].tim, -1);
        
        i = mid, j = R;
        //左边大于他的
        while(j > mid && i >= L) {
            if(res[j].val < res[i].val)
                add(res[i--].tim, 1);
            else 
                res[j].ans += getsum(m+1)-getsum(res[j--].tim);
        }
        while(j > mid)
            res[j].ans += getsum(m+1)-getsum(res[j--].tim);
        for(int r = mid; r > i; --r)
            add(res[r].tim, -1);
        sort(res+L, res+R+1, cmpval);
    }
    
    bool cmp2(Node a, Node b) {
        return a.tim < b.tim;
    }
    
    
    int main() {
        scanf("%d%d", &n, &m);
        int t;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &t);
            res[i] = {t};
            Cache[t] = i;
        }
        for(int i = 1; i <= m; ++i) {
            scanf("%d", &t);
            res[Cache[t]].tim = i;
        }
        for(int i = 1; i <= n; ++i)
            if(res[i].tim == 0)
                res[i].tim = m + 1;
        LL ans = 0;
        for(int i = 1; i <= n; ++i) {
            add(res[i].val, 1);
            ans += i - getsum(res[i].val);
        }
        for(int i = 1; i <= n; ++i)
            add(res[i].val, -1);
        CDQ(1, n);
        sort(res+1, res+1+n, cmp2);
        for(int i = 1; i <= m; ++i) printf("%lld
    ", ans), ans -= res[i].ans;
        return 0;
    }
    View Code
  • 相关阅读:
    CSS水平居中和垂直居中解决方案
    MVC 发布到IIS中的配置方法
    iis配置asp.net常见验证失败问题解决方案
    fiddler无法抓取chrome解决方法
    VBA取得EXCEL表格中的行数和列数
    Oracle VM VirtualBox做好虚拟硬盘后,如何进一步修改虚拟硬盘的大小
    SQL Server 2008用'sa'登录失败,启用'sa'登录的办法
    unity3d中物体的控制
    GameObject数组
    Linux进程与线程概述
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12210251.html
Copyright © 2011-2022 走看看