Codeforces 414C Mashmokh and Reverse Operation 归并排序在线求交换序列后逆序数
来源:互联网 发布:socket 网络调试工具 编辑:程序博客网 时间:2024/04/29 23:15
题目链接:http://codeforces.com/contest/414/problem/C
先复制一个思路:
解法: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各个区间翻转后的逆序数就可以了。
题意:
给定 2^n 长的序列
下面que个询问,对于每个询问 u,
1、先把 序列分段分成: [0, 2^u-1], [2^u, 2^(u+1)-1],······
2、再把每段都翻转一下。
3、输出此时序列的逆序数。
思路:首先我们要得到:
对于一个序列[l,r) 的翻转 =
1、 将该序列的[l,mid), [mid,r)}交换
2、[l,mid/2),[mid/2,mid)交换 + [mid,mid+mid/2),[mid+mid/2,r) 交换
3、 如此递归下去
例如:12345678-> 87654321
等价于 1234 | 5678 -> 5678 | 1234 -> 7856 | 3412 -> 8765 | 4321
于是把序列分层,得到n层
对于每一层[l, r] 的逆序数对分为:
1、两个数字都在[l,mid) 内的 +两个数字都在 [mid,r]内的
2、一个数字在[l,mid),一个数字在[mid,r]
3、若区间内只有2个数则只有第二种情况,第一种情况答案为0.
所以累加上每层的区间之间的逆序数即为整个序列的逆序数
而交换一下区间就是 2、中结果变成 : 一个数字在[mid,r] ,一个数字在[l,mid )
即每层的2有2种答案。
预处理出每层的2个答案,累加即可。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <string>using namespace std;#define N 20#define ll __int64ll a[1 << N], n, m;//一个序列[l,r) 的翻转 = 将该序列的{[l,mid), [mid,r)} 交换 + ({[l,mid/2),[mid/2,mid)} + {[mid,mid+mid/2),[mid+mid/2,r)} ) + 如此递归下去ll sum[N + 1][2]; //sum[deep]表示 求和每段[l,r]的:[l,mid)和[mid,r) 之间的逆序数void dfs(ll l, ll r, ll deep){if(l+1 >= r)return ;ll mid = (l+r)/2;dfs(l, mid, deep-1);dfs(mid, r, deep-1);ll cnt = 0;for(ll i = l; i < mid; i++)cnt += lower_bound(a+mid, a+r, a[i]) - (a+mid);sum[deep][0] += cnt; cnt = 0;for(ll i = mid; i < r; i++)cnt += lower_bound(a+l, a+mid, a[i]) - (a+l);sum[deep][1] += cnt;inplace_merge(a+l, a+mid, a+r);}int main(){ll n, i, que, u;ll er[30];er[0] = 1;for(i=1;i<30;i++)er[i] = er[i-1]*2;while(~scanf("%I64d",&n)){memset(sum, 0, sizeof sum);for(i = 0; i < er[n]; i++)scanf("%I64d",&a[i]);dfs(0, er[n], n);scanf("%I64d",&que);while(que--){scanf("%I64d",&u);ll ans = 0;while(u--)swap(sum[u+1][0], sum[u+1][1]);for(i=0; i <= n; i++) ans += sum[i][0];printf("%I64d\n",ans);}}return 0;}
- Codeforces 414C Mashmokh and Reverse Operation 归并排序在线求交换序列后逆序数
- CodeForces 414 C.Mashmokh and Reverse Operation(归并排序)
- CodeForces 414 C. Mashmokh and Reverse Operation
- 归并排序 逆序数 Codeforces 414 C
- CF 414C Mashmokh and Reverse Operation(分治)
- 利用归并排序求有限序列的逆序数
- 归并排序,求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 归并排序求逆序数
- 安卓蓝牙开发
- 3月二手住宅市场缓慢回温
- 404页面该怎么做?
- 汤阳光OA视频中JBPM中关于审批流程笔记
- [LeetCode] Pascal's Triangle II
- Codeforces 414C Mashmokh and Reverse Operation 归并排序在线求交换序列后逆序数
- opencv源码解析之(6):hog源码分析
- SVNX使用教程
- Python正则表达式(一):元字符
- 解析叠片式过滤器日常常见问题
- C标签
- visual studio c++ 项目中的(不)需要加入到svn库中的
- Xamarin和微软发起.NET基金会
- ViewController详解