zoukankan      html  css  js  c++  java
  • bzoj 3289 : Mato的文件管理 (莫队+树状数组)

    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=3289

    思路:

    求区间最小交换的次数将区间变成一个不降序列其实就是求区间逆序对的数量,这道题的样例解释可以不看,样例应该是

    4和2换再和3换,这样就是最小的交换次数变成不降序列,从样例我们可以看出其实这就是求逆序对的过程,但是这道题是

    区间询问逆序对的个数,我们需要离线处理所有询问,然后用树状数组维护数组中比这个数小的数的数量,用莫队逐个维护

    就好了,

    我们可以推出删除,增加一个数对当前区间逆序对数量变化的关系:

    1. 在序列的前端添加一个数,那么序列逆序对的数量就会增加序列中比这个数小的数的数量

    2.在序列的前端删除一个数,那么序列中逆序对的数量就会减少序列中比这个数小的数的数量

    3.在序列的末端添加一个数,那么序列中逆序对的数量就会增加序列中比这个数大的数的数量

    4.在序列的末端删除一个数,那么序列中逆序对的数量就会增加序列中比这个数大的数的数量

    这里树状数组的作用就是维护序列中比某个数大/小的数的数量

    实现代码;

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5+10;
    int blo,n,m,a[M],b[M],c[M<<2],num[M];
    int lowbit(int x){ return x&(-x);}
    
    int getsum(int x){
        int sum = 0;
        while(x>0){
            sum += c[x];
            x -= lowbit(x);
        }
        return sum;
    }
    
    void update(int x,int val){
        while(x <= n){
            c[x] += val;
            x += lowbit(x);
        }
    }
    
    struct node{
        int l,r,id;
    }q[M];
    
    bool cmp(node a,node b){
        if(a.l/blo == b.l/blo) return a.r < b.r;
        return a.l < b.l;
    }
    
    int main()
    {
        scanf("%d",&n);
        blo = sqrt(n);
        for(int i = 1;i <= n;i ++){
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort(b+1,b+n+1);
        for(int i = 1;i <= n;i ++)
            a[i] = lower_bound(b+1,b+1+n,a[i])-b;
        scanf("%d",&m);
        for(int i = 1;i <= m;i ++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id = i;
        }
        sort(q+1,q+1+m,cmp);
        int l = 1,r = 0,ans = 0;
        for(int i = 1;i <= m;i ++){
            while(l < q[i].l) update(a[l],-1),ans -= getsum(a[l]-1),l++;
            while(r < q[i].r) r++,ans += getsum(n)-getsum(a[r]),update(a[r],1);
            while(l > q[i].l) l--,ans += getsum(a[l]-1),update(a[l],1);
            while(r > q[i].r) update(a[r],-1),ans -= getsum(n) - getsum(a[r]),r--;
            num[q[i].id] = ans;
        }
        for(int i = 1;i <= m;i ++)
            printf("%d
    ",num[i]);
        return 0;
    }
  • 相关阅读:
    Project Euler 613 Pythagorean Ant(概率+积分)
    Codeforces Beta Round #24 D. Broken robot (打表找规律)
    Codeforces Beta Round #17 D. Notepad (数论 + 广义欧拉定理降幂)
    bzoj4916-神犇和蒟蒻
    bzoj4176-Lucas的数论
    bzoj2788-Festival
    bzoj2839-集合计数
    bzoj1853-大包子的幸运数字
    bzoj3622-已经没有什么好害怕的的了
    bzoj2669-局部极小值
  • 原文地址:https://www.cnblogs.com/kls123/p/9429572.html
Copyright © 2011-2022 走看看