• BZOJ 2141: 排队 CDQ分治+bit


    2141: 排队


    Description

    排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足ihj的(i,j)数量。幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

    Input

    第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi¬,表示交换位置ai与位置bi的小朋友。

    Output

    输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度。

    Sample Input

    【样例输入】
    3
    130 150 140
    2
    2 3
    1 3

    Sample Output

    1
    0
    3
    【样例说明】
    未进行任何操作时,(2,3)满足条件;
    操作1结束后,序列为130 140 150,不存在满足i<j且hi>hj的(i,j)对;
    操作2结束后,序列为150 140 130,(1,2),(1,3),(2,3)共3对满足条件的(i,j)。
    【数据规模和约定】
    对于100%的数据,1≤m≤2*103,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。

    HINT

    题解:

      分块+bit可做

      用来练习cdq分治,其实和3295动态逆序对是一样的

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 5e5+10, M = 1e3+20,inf = 2e9,mod = 1e9+7;
    
    int C[N],n,m,a[N],b[N];
    void update(int x,int c) {
        for(int i = x; i <= n; i += i&(-i)) {
            C[i] += c;
        }
    }
    int sum(int x) {
        int ret = 0;
        for(int i = x; i; i -= i&(-i)) {
            ret += C[i];
        }
        return ret;
    }
    struct ss{
        int l,r,t,qid,type;
        ss(){}
        ss(int a,int b,int c,int d,int e):l(a),r(b),t(c),qid(d),type(e){}
        bool operator < (const ss &x) const {
            if(l == x.l) return t < x.t;
            else return l < x.l;
        }
    }q[N],t[N];
    int ans[N];
    void cdq(int ll,int rr) {
        if(ll == rr) return ;
        for(int i = ll; i <= rr; ++i) {
            if(q[i].t <= mid) update(q[i].r,q[i].type);
            else ans[q[i].qid] += q[i].type*(sum(n) - sum(q[i].r));
        }
        for(int i = ll; i <= rr; ++i)
            if(q[i].t <= mid) update(q[i].r,-q[i].type);
        for(int i = rr; i >= ll; --i) {
            if(q[i].t <= mid) update(q[i].r,q[i].type);
            else {
                ans[q[i].qid] += q[i].type*(sum(q[i].r-1));
            }
        }
         for(int i = ll; i <= rr; ++i)
            if(q[i].t <= mid) update(q[i].r,-q[i].type);
        int L1 = ll, R1 = mid+1;
        for(int i = ll; i <= rr; ++i)
            if(q[i].t <= mid) t[L1++] = q[i];
         else t[R1++] = q[i];
         for(int i = ll; i <= rr; ++i) q[i] = t[i];
         cdq(ll,mid);cdq(mid+1,rr);
    }
    int main() {
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i)
            scanf("%d",&a[i]),b[i] = a[i];
        sort(b+1,b+n+1);
        int SC = unique(b+1,b+n+1) - b - 1;
        int cnt = 0;
        for(int i = 1; i <= n; ++i) {
            a[i] = lower_bound(b+1,b+SC+1,a[i]) - b;
            q[++cnt] = ss(i,a[i],cnt,0,1);
        }
        scanf("%d",&m);
        for(int i = 1; i <= m; ++i) {
            int x,y;
            scanf("%d%d",&x,&y);
            q[++cnt] = ss(x,a[y],cnt,i,1);
            q[++cnt] = ss(x,a[x],cnt,i,-1);
            q[++cnt] = ss(y,a[x],cnt,i,1);
            q[++cnt] = ss(y,a[y],cnt,i,-1);
            swap(a[x],a[y]);
        }
        sort(q+1,q+cnt+1);
        cdq(1,cnt);
        printf("%d
    ",ans[0]);
        for(int i = 1; i <= m; ++i) ans[i] += ans[i-1];
        for(int i = 1; i <= m; ++i) cout<<ans[i]<<endl;
        return 0;
    }
  • 相关阅读:
    事务的隔离级别
    常用linux命令
    cpu.load avg和cpu使用率的区别
    【Leetcode】55. Jump Game
    【Leetcode】322. coin-change
    34.find-first-and-last-position-of-element-in-sorted-array
    【LeetCode】56.merge-intervals
    Leetcode】210.course-schedule-ii
    基于Thread实现自己的定时器Timer
    Boost--内存管理--(1)智能指针
  • 原文地址:https://www.cnblogs.com/zxhl/p/7190078.html
Copyright © 2020-2023  润新知