• 洛谷 P1975 [国家集训队]排队 Label:块内排序+树状数组


    题目描述

    排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。

    红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第i个小朋友的身高为hi,我们定义一个序列的杂乱程度为:满足i<j且hi>hj的(i,j)数量。

    幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的杂乱程度。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的杂乱程度。

    输入输出格式

    输入格式:

    第一行为一个正整数n,表示小朋友的数量;

    第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;

    第三行为一个正整数m,表示交换操作的次数;

    以下m行每行包含两个正整数ai和bi­,表示交换位置ai与位置bi的小朋友。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    3
    130 150 140
    2
    2 3
    1 3
    输出样例#1: 复制
    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)。

    对于15%的数据, n,m le 15n,m15 ;

    对于30%的数据, n,m le 200n,m200 ;

    在剩下的70%数据中:

    存在15%的数据, h_ihi 各不相同;

    存在15%的数据, 1^{10} le h_i le 1^{60}110hi160 ;

    以上两类数据不存在交集。

    对于100%的数据, 1 le m le 2 imes 10^31m2×103 , 1 le n le 2 imes 10^41n2×104 , 1 le h_i le 10^91hi109 , a_i e b_iaibi , 1 le a_i,b_i le n1ai,bin。

    代码

    直接暴力分块,然后在每一个块内排序。

    查询时可以在每一个块内二分。

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #define M 210
    #define N 20101
     
    using namespace std;
     
    int n, m, t, S, C, ans;
    int a[N], b[N], c[N], st[M], ed[M], belong[N], sorted[M][M], len[M];
     
    inline int read()
    {
        int x = 0, f = 1;
        char ch = getchar();
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
        for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
        return x * f;
    }
     
    inline int query(int x)
    {
        int ret = 0;
        for(; x; x -= x & -x) ret += c[x];
        return ret;
    }
     
    inline void add(int x)
    {
        for(; x <= m; x += x & -x) c[x]++;
    }
     
    inline void init()
    {
        int i, j;
        S = sqrt(n);
        for(i = 1; i <= n; i += S)
        {
            st[++C] = i;
            ed[C] = min(i + S - 1, n);
            len[C] = ed[C] - st[C] + 1;
        }
        for(i = 1; i <= C; i++)
        {
            for(j = st[i]; j <= ed[i]; j++)
                belong[j] = i, sorted[i][j - st[i] + 1] = a[j];
            sort(sorted[i] + 1, sorted[i] + len[i] + 1);
        }
    }
     
    inline void solve(int x, int y)
    {
        if(x > y) swap(x, y);
        int i, l = belong[x], r = belong[y], tmp;
        if(l == r)
            for(i = x + 1; i < y; i++)
            {
                ans -= (a[i] < a[x]);
                ans += (a[i] > a[x]);
                ans -= (a[i] > a[y]);
                ans += (a[i] < a[y]);
            }
        else
        {
            for(i = l + 1; i < r; i++)
            {
                ans -= lower_bound(sorted[i] + 1, sorted[i] + len[i] + 1, a[x]) - sorted[i] - 1;
                ans += len[i] - (upper_bound(sorted[i] + 1, sorted[i] + len[i] + 1, a[x]) - sorted[i]) + 1;
                ans -= len[i] - (upper_bound(sorted[i] + 1, sorted[i] + len[i] + 1, a[y]) - sorted[i]) + 1;
                ans += lower_bound(sorted[i] + 1, sorted[i] + len[i] + 1, a[y]) - sorted[i] - 1;
            }
            for(i = x + 1; i <= ed[l]; i++)
            {
                ans -= (a[i] < a[x]);
                ans += (a[i] > a[x]);
                ans -= (a[i] > a[y]);
                ans += (a[i] < a[y]);
            }
            for(i = st[r]; i < y; i++)
            {
                ans -= (a[i] < a[x]);
                ans += (a[i] > a[x]);
                ans -= (a[i] > a[y]);
                ans += (a[i] < a[y]);
            }
        }
        if(a[x] > a[y]) ans--;
        if(a[x] < a[y]) ans++;
        swap(a[x], a[y]);
        for(i = st[l]; i <= ed[l]; i++) sorted[l][i - st[l] + 1] = a[i];
        for(i = st[r]; i <= ed[r]; i++) sorted[r][i - st[r] + 1] = a[i];
        sort(sorted[l] + 1, sorted[l] + len[l] + 1);
        sort(sorted[r] + 1, sorted[r] + len[r] + 1);
    }
     
    int main()
    {
        int i, x, y;
        n = read();
        for(i = 1; i <= n; i++) a[i] = b[i] = read();
        sort(b + 1, b + n + 1);
        m = unique(b + 1, b + n + 1) - b - 1;
        for(i = 1; i <= n; i++)
        {
            a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b;
            ans += i - query(a[i]) - 1, add(a[i]);
        }
        printf("%d
    ", ans);
        init();
        t = read();
        while(t--)
        {
            x = read();
            y = read();
            solve(x, y);
            printf("%d
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    linux下解除端口占用
    设计模式(二)观察者模式
    设计模式(一) 策略模式
    loj #6235. 区间素数个数
    loj #2013. 「SCOI2016」幸运数字
    loj #6014. 「网络流 24 题」最长 k 可重区间集
    loj #6013. 「网络流 24 题」负载平衡
    loj #2255. 「SNOI2017」炸弹
    loj #2051. 「HNOI2016」序列
    loj #6122. 「网络流 24 题」航空路线问题
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/9394001.html
Copyright © 2020-2023  润新知