【题解】洛谷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\n", 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\n", ans);
    }
    return 0;
}

 

posted @ 2018-03-01 21:46  Twilight_Sx  阅读(141)  评论(0编辑  收藏  举报