zoukankan      html  css  js  c++  java
  • 【BZOJ3289】Mato的文件管理-莫队算法+树状数组

    测试地址:Mato的文件管理
    做法:本题需要用到莫队算法+树状数组。
    在想区间维护之前,首先要思考这个最小交换次数到底是个什么东西。实际上,答案就是这个区间中的逆序对数。我们现在证明一下这个结论。
    我们知道排完序后逆序对数为0,而且只有这样的一个状态逆序对数才有可能为0,而其他状态都是有逆序对的。显然对于这些状态一定存在一个i使得Ai>Ai+1,那么将AiAi+1互换,那么逆序对数1,而其他逆序对之间的顺序并没有被影响,所以每次交换最多使逆序对数1。因此最小交换次数就是每次交换逆序对数都1,一直到逆序对数归零的次数,那么这个次数就是逆序对数了。
    于是问题变成求区间逆序对数,用线段树等数据结构好像不好维护,想到使用莫队算法。考虑两种情况:
    一、从区间的左边增删元素。这种情况下,增删一个元素对逆序对数的影响是加(减)区间中比它小的数的个数。
    二、从区间的右边增删元素。这种情况下,增删一个元素对逆序对数的影响是加(减)区间中比它大的数的个数。
    要找区间中比一个数大或小的数的个数,很容易想到用树状数组维护,那么莫队算法的一次转移是O(logn)的,所以总的时间复杂度就是O(nnlogn)的了,可以通过此题。
    还有一点要注意的是,原数列中的数字并没有限定范围,需要离散化。
    以下是本人代码:

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    int n,m,a[50010],blocklen,block[50010];
    ll sum[50010],ans[50010],ssum;
    struct forsort
    {
        int id,val;
    }f[50010];
    struct Query
    {
        int id,l,r;
    }q[50010];
    
    bool cmpf(forsort a,forsort b)
    {
        return a.val<b.val;
    }
    
    bool cmpq(Query a,Query b)
    {
        if (block[a.l]!=block[b.l]) return block[a.l]<block[b.l];
        else return a.r<b.r;
    }
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void BITadd(int x,ll c)
    {
        for(int i=x;i<=n;i+=lowbit(i))
            sum[i]+=c;
    }
    
    ll BITsum(int x)
    {
        ll ans=0;
        for(int i=x;i;i-=lowbit(i))
            ans+=sum[i];
        return ans;
    }
    
    void expand(int x,int side,ll add)
    {
        int v=a[x];
        ll s;
        if (side) s=BITsum(n)-BITsum(v);
        else s=BITsum(v-1);
        ssum+=add*s;
        BITadd(v,add);
    }
    
    void Mo()
    {
        int l=1,r=0;
        ssum=0;
        for(int i=1;i<=m;i++)
        {
            while(q[i].l<l) expand(--l,0,1);
            while(q[i].r>r) expand(++r,1,1);
            while(q[i].l>l) expand(l++,0,-1);
            while(q[i].r<r) expand(r--,1,-1);
            ans[q[i].id]=ssum;
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        blocklen=(int)sqrt(n);
        for(int i=1;i<=n;i++)
        {
            f[i].id=i;
            scanf("%d",&f[i].val);
            block[i]=i/blocklen;
        }
        sort(f+1,f+n+1,cmpf);
    
        int tot=0;
        for(int i=1;i<=n;i++)
        {
            if (i==1||f[i].val!=f[i-1].val) tot++;
            a[f[i].id]=tot;
        }
    
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            q[i].id=i;
            scanf("%d%d",&q[i].l,&q[i].r);
        }
        sort(q+1,q+m+1,cmpq);
    
        Mo();
        for(int i=1;i<=m;i++)
            printf("%lld
    ",ans[i]);
    
        return 0;
    }
  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793530.html
Copyright © 2011-2022 走看看