zoukankan      html  css  js  c++  java
  • 【题解】洛谷P1975排序

    分块,注意重复的值之间的处理。跟普通分块的操作一样的啦,具体可以参见‘不勤劳的图书管理员’。

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 500000
    #define lowbit(i) i & (-i) 
    #define int long long
    int n, m, cnt, ans, B, c[200][maxn];
    struct node
    {
        int num, id, rank;
    }a[30000];
    
    int read()
    {
        int x = 0;
        char c;
        c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x;
    }
    
    int Get_ans(int x, int y)
    {
        if(a[x].rank < a[y].rank) return 1;
        else if(a[x].rank > a[y].rank) return -1;
        return 0;
    }
    
    bool cmp1(node a, node b)
    {
        if(a.num != b.num) return a.num < b.num;
        return a.id < b.id;
    }
    
    bool cmp2(node a, node b)
    {
        return a.id < b.id;
    }
    
    void update(int opt, int x, int sum)
    {
        if(!x) return;
        for(int i = x; i <= cnt; i += lowbit(i))
            c[opt][i] += sum;
    }
    
    int query(int opt, int x)
    {
        if(x < 0) return 0;
        int ans = 0;
        for(int i = x; i; i -= lowbit(i))
            ans += c[opt][i];
        return ans;
    }
    
    signed main()
    {
        n = read(); 
        B = sqrt(n);
        for(int i = 1; i <= n; i ++)
            a[i].num = read(), a[i].id = i;
        sort(a + 1, a + 1 + n, cmp1);
        a[0].rank = 1;
        for(int i = 1; i <= n; i ++)
            if(a[i].num == a[i - 1].num) a[i].rank = a[i - 1].rank;
            else a[i].rank = ++ cnt;
        sort(a + 1, a + 1 + n, cmp2);
        for(int i = 1; i <= n; i ++)
            update(i / B, a[i].rank, 1);
        for(int i = n; i >= 1; i --)
        {
            ans += query(n / B + 1, a[i].rank - 1);
            update(n / B + 1, a[i].rank, 1);
        }
        m = read();
        cout << ans << endl;
        for(int i = 1; i <= m; i ++)
        {
            int x = read(), y = read();
            if(x > y) swap(y, x);
            int p = x / B, q = y / B;
            if(a[x].rank < a[y].rank) ans ++;
            else if(a[x].rank > a[y].rank) ans --;
            if(p == q)
            {
                for(int i = x + 1; i < y; i ++)
                    ans += Get_ans(x, i) + Get_ans(i, y);
                swap(a[x], a[y]);
                printf("%lld
    ", ans);
                continue;
            }
            for(int i = x + 1; i < (p + 1) * B; i ++)
                if(i <= n) ans += Get_ans(x, i) + Get_ans(i, y);
            for(int i = q * B; i < y; i ++)
                ans += Get_ans(i, y) + Get_ans(x, i);
            for(int i = p + 1; i < q; i ++)
            {
                ans = (ans - query(i, a[x].rank - 1) + query(i, a[y].rank - 1));
                ans = (ans - query(i, a[x].rank)  + query(i, a[y].rank));
            }
            update(p, a[x].rank, -1), update(q, a[y].rank, -1);
            update(q, a[x].rank, 1), update(p, a[y].rank, 1);
            swap(a[x], a[y]);
            printf("%lld
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    给树莓派安装中文环境
    windows中让secureCRT正确显示中文(ssh)
    C# net winform wpf 发送post数据和xml到网页
    WebDav协议基于HTTP 1
    WCF WEB HTTP请求 WCF REST FUL
    WPF黑色背景下常用控件样式
    解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接
    WPF 漏斗控件 等待沙漏效果
    WPF 资源管理器 WPF Explorer
    WPF MVVM 关闭窗体
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/8490705.html
Copyright © 2011-2022 走看看