Codeforces 414C Mashmokh and Reverse Operation

题意:给你2^n个数,每次操作将其分成2^k份,对于每一份内部的数进行翻转,每次操作完后输出操作后的2^n个数的逆序数。

解法:2^n个数,可以联想到建立一棵二叉树的东西,比如  2,1,4,3就可以建成下面这样

                                                    [2,1,4,3]                        level 2

                                                   /               \

                                              [2,1]              [4,3]                  level 1

                                           /        \              /     \

                                        [2]         [1]        [4]    [3]              level 0

然后算某个区间的逆序数的时候[2,1,4,3]实际上就是算[2,1],[4,3]的逆序数再加上[2,1],[4,3]之间的逆序数,思路和归并排序是一样的。

然后我们看下每次翻转,假如我们分成2^k份,我们会发现,对于level k+1层以上的逆序数是不会改变的,但是level k~level 0的逆序数对会翻转,我们只需要知道level k~level 0各个区间翻转后的逆序数就可以了。 

所以做法就有点类似于归并求逆序数,对于每个结点,记inv[0]为不翻转时的逆序数,inv[1]为翻转的时候的逆序数,然后我们记sum[k][0]和sum[k][1] 为该层所有结点的inv[0]的和 以及inv[1]的和。 然后每次操作就是将 sum[k~0]的0,1值交换,然后逆序数就是sum[n~0][0]的和。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define ll long long
#define maxn 2000000
using namespace std;

ll a[maxn];
int n;

ll sum[25][2];

void build(int dep,int L, int R)
{
	if (dep == 0){
		sum[dep][0] = sum[dep][1] = 0; return;
	}
	int M = (L + R) >> 1;
	build(dep - 1, L, M); build(dep - 1, M + 1, R);
	for (int i = L; i <= M; i++){
		sum[dep][1] += a+R+1-upper_bound(a + M + 1, a + R + 1, a[i]);
		sum[dep][0] += lower_bound(a + M + 1, a + R+1, a[i]) - (a + M + 1);
	}
	sort(a + L, a + R + 1);
};

int main()
{
	while (cin >> n)
	{
		memset(sum, 0, sizeof(sum));
		int tot = 1 << n;
		for (int i = 1; i <= tot; i++){
			scanf("%I64d", a + i);
		}
		build(n, 1, tot);
		int m, q;
		cin >> m;
		for (int i = 0; i < m; i++){
			scanf("%d", &q);
			for (int j = q; j >= 0; j--){
				swap(sum[j][0], sum[j][1]);
			}
			ll ans = 0;
			for (int j = n; j >= 0; j--){
				ans += (ll)sum[j][0];
			}
			printf("%I64d\n", ans);
		}
	}
	return 0;
}

 

posted @ 2014-04-07 19:14  chanme  阅读(367)  评论(0编辑  收藏  举报