[BZOJ] 2141 - Atlantis - Queue - Tree Array Reversal Pair - Block interval smaller than k

2141: Queue

Time Limit:  4 Sec   Memory Limit:  259 MB
Submit:  2506   Solved:  982
[ Submit ][ Status ][ Discuss ]

Description

Sitting in rows, eating fruit, the fruit is sweet and long, and everyone laughs. One for you, one for me, the big one will be given to you, and the small one for me. After eating Guoguo, you will sing a song, and everyone will be happy and harmonious. The children of Hongxing Kindergarten lined up in a long line, ready to eat fruit. However, because the heights of the children are different, the ranks of the children are disordered, which is extremely unsightly. Let the height of the i-th child be hi, and we define the disorder degree of a sequence as: the number of (i, j) satisfying ihj. The kindergarten aunt will select two children each time and exchange their positions. Please help to calculate the clutter of the sequence after each exchange. In order to facilitate the statistics of the kindergarten aunt, you should also output the clutter of the sequence when no swap operation is performed.

Input

The first line is a positive integer n, indicating the number of children; the second line contains n positive integers h1, h2, ..., hn separated by spaces, which in turn indicate the height of the children in the initial queue; the third line is a positive integer m, Indicates the number of swap operations; each of the following m lines contains two positive integers ai and bi¬, representing the children who exchange positions ai and bi.

Output

The output file has m lines in total, and a positive integer in the i-th line indicates the disorder degree of the sequence after the exchange operation i is completed.

Sample Input

【Sample input】
3
130 150 140
2
2 3
1 3

Sample Output

1
0
3
[Example description]
When no operation is performed, (2,3) satisfies the condition;
after operation 1 ends, the sequence is 130 140 150, and there is no (i,j) pair that satisfies ihj;
after operation 2 ends, The sequence is 150 140 130, (1,2), (1,3), (2,3), a total of 3 pairs of (i,j) that satisfy the conditions.
[Data scale and convention]
For 100% data, 1≤m≤2*103, 1≤n≤2*104, 1≤hi≤109, ai≠bi, 1≤ai, bi≤n.

HINT

Source


clear meaning

Direct 1Y one shot into the soul is beautiful


A sequence of length n m operations, each operation swaps two numbers in different positions
Ask the number of reverse order pairs after each operation



First, use line segment tree or merge sort or tree array to find the number of initial reverse order pairs

Then look at each operation

Let the position on the left be l and the position on the right be r

Only the interval [l, r] will have an impact on the global

[l, r] Outside the interval, what is less than or less than, what is greater than or greater than

For the [l, r] interval, we need to count how many are smaller than ma[l], ma[r] and how many are greater than ma[l], ma[r]

Then consider using block to solve

The specific solution is similar to the number of colors http://blog.csdn.net/yiranluoshen/article/details/78224787

Sort within each block
Direct binary search for complete blocks for each search
The complexity is O(log(sqrt(n)))

A little brain-burning is how to update when swapping

我的解法是对于原数组直接交换

在排序的数组先二分查找原数据的位置
然后更新
然后再移动

这样每次更新的时候复杂度是O(log(sqrt(n)) + sqrt(n))

1Y的时候还是很惊喜的

1300ms不算快

发现有人600ms

复杂度好像是O(sqrt(n)logn)
对每个块建一个树状数组

懵掉
下次研究
#include <bits/stdc++.h>
#define pb push_back
using namespace std;

const int N = 20010;

int n, m;
int bits[N];
int ma[N];
int cp[N];///每个块排序后储存的数组
int block;
int num;
int bo[N];
int bl[N];
int br[N];
int ans;
int len;
vector<int> id;

int getid(int x)
{
    return lower_bound(id.begin(), id.end(), x) - id.begin() + 1;
}

int lowbit(int x)
{
    return x & -x;
}

int quary(int x)
{
	int ans = 0;

	while(x > 0){
		ans += bits[x];
		x -= lowbit(x);
	}

	return ans;
}

void update(int x, int v)
{
	while(x <= len){
		bits[x] += v;
		x += lowbit(x);
	}
}

void build()
{
    block = sqrt(n);
    num = n / block;
    if(n % block){
        num ++;
    }
    for(int i = 1; i <= n; i ++){
        bo[i] = (i - 1) / block + 1;
    }
    for(int i = 1; i <= num; i ++){
        bl[i] = (i - 1) * block + 1;
        br[i] = i * block;
    }
    br[num] = n;
    for(int i = 1; i <= num; i ++){
        for(int j = bl[i]; j <= br[i]; j ++){
            cp[j] = ma[j];
        }
        sort(cp + bl[i], cp + br[i] + 1);
    }
}

void quary_block(int l, int r, int v, int t)	///交换之前就计算,比ma[l]小的ans--   比 ma[r]小的ans++ 这样就能把两个合并在一起
{
	int x = bo[l];
	int y = bo[r];

	if(x == y){
		for(int i = l; i <= r; i ++){
			if(ma[i] < v){
				ans -= t;
			}
			else if(ma[i] > v){
				ans += t;
			}
		}
	}
	else{
		for(int i = l; i <= br[x]; i ++){
            if(ma[i] < v){
				ans -= t;
			}
			else if(ma[i] > v){
				ans += t;
			}
        }
        for(int i = x + 1; i < y; i ++){
	        ans -= t * (lower_bound(cp + bl[i], cp + br[i] + 1, v) - cp - bl[i]);
	    	ans += t * ((br[i] - bl[i] + 1) - (upper_bound(cp + bl[i], cp + br[i] + 1, v) - cp - bl[i]));
	    }
        for(int i = bl[y]; i <= r; i ++){
            if(ma[i] < v){
				ans -= t;
			}
			else if(ma[i] > v){
				ans += t;
			}
        }
	}
}

void exchange(int l, int r)
{
    if(l > r){
        return ;
    }
	int t;
	int opx;
	int opy;
	int x = bo[l];
	int y = bo[r];

    if(ma[l] < ma[r]){
        ans ++;
    }
    else if(ma[l] > ma[r]){
        ans --;
    }
	swap(ma[l], ma[r]);
	opx = lower_bound(cp + bl[x], cp + br[x] + 1, ma[l]) - cp;
	opy = lower_bound(cp + bl[y], cp + br[y] + 1, ma[r]) - cp;
	cp[opx] = ma[r];
	cp[opy] = ma[l];
	t = opx;
	while(t - 1 >= bl[x] && cp[t - 1] > cp[t]){
		swap(cp[t], cp[t - 1]);
		t --;
	}
	while(t <= br[x] && cp[t + 1] < cp[t]){
		swap(cp[t], cp[t + 1]);
		t ++;
	}
	t = opy;
	while(t - 1 >= bl[y] && cp[t - 1] > cp[t]){
		swap(cp[t], cp[t - 1]);
		t --;
	}
	while(t <= br[y] && cp[t + 1] < cp[t]){
		swap(cp[t], cp[t + 1]);
		t ++;
	}
}

int main(int argc, char const *argv[])
{
	while(scanf("%d", &n) == 1){
		ans = 0;
		memset(bits, 0, sizeof(bits));
		for(int i = 1; i <= n; i ++){
			scanf("%d", &ma[i]);
			id.pb(ma[i]);
		}
		sort(id.begin(), id.end());
    	id.erase(unique(id.begin(), id.end()), id.end());
    	len = id.size();
		for(int i = 1; i <= n; i ++){
            update(getid(ma[i]), 1);
			ans += i - quary(getid(ma[i]));
		}
		printf("%d\n", ans);
		scanf("%d", &m);
		for(int i = 0; i < m; i ++){
			int l, r;

			scanf("%d%d", &l, &r);
			if(r < l){
                swap(r,l);
			}
			quary_block(l + 1, r - 1, ma[l], 1);
			quary_block(l + 1, r - 1, ma[r], -1);
			exchange(l, r);
			printf("%d\n", ans);
		}
	}


	return 0;
}


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325559899&siteId=291194637