BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程
Posted 繁凡さん
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程相关的知识,希望对你有一定的参考价值。
整理的算法模板合集: ACM模板
实际上是一个全新的精炼模板整合计划
题目链接
https://hydro.ac/d/bzoj/p/2141
是 hydro 的 BZOJ 修复工程 !(我也去领了一点题慢慢修着玩,这题就是我修的嘿嘿嘿)
题目描述
排排坐,吃果果,生果甜嗦嗦,大家笑呵呵。你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和。
红星幼儿园的小朋友们排起了长长地队伍,准备吃果果。不过因为小朋友们的身高有所区别,排成的队伍高低错乱,极不美观。设第 i i i 个小朋友的身高为 h i h_i hi 。
幼儿园阿姨每次会选出两个小朋友,交换他们的位置,请你帮忙计算出每次交换后,序列的逆序对数。为方便幼儿园阿姨统计,在未进行任何交换操作时,你也应该输出该序列的逆序对数。
输入格式
第一行为一个正整数 n n n ,表示小朋友的数量;
第二行包含 n n n 个由空格分隔的正整数 h 1 , h 2 , … , h n h_1,h_2,\\dots,h_n h1,h2,…,hn ,依次表示初始队列中小朋友的身高;
第三行为一个正整数 m m m ,表示交换操作的次数;
以下 m m m 行每行包含两个正整数 a i a_i ai 和 b i b_i bi ,表示交换位置 a i a_i ai 与位置 b i b_i bi 的小朋友。
输出格式
输出文件共 m + 1 m+1 m+1 行,第 i i i 行一个正整数表示交换操作 i i i 结束后,序列的杂乱程度。
输入样例
3
130 150 140
2
2 3
1 3
输出样例
1
0
3
数据规模和约定
对于 100 % 100\\% 100% 的数据, 1 ≤ m ≤ 2 × 1 0 3 1\\le m\\le 2\\times 10^3 1≤m≤2×103, 1 ≤ n ≤ 2 × 1 0 4 1\\le n\\le 2\\times 10^4 1≤n≤2×104, 1 ≤ h i ≤ 1 0 9 1\\le h_i\\le 10^9 1≤hi≤109, a i ≠ b i a_i\\neq b_i ai=bi, 1 ≤ a i , b i ≤ n 1\\le a_i,b_i\\le n 1≤ai,bi≤n。
提示
【样例说明】
未进行任何操作时, ( 2 , 3 ) (2,3) (2,3) 为逆序对;
操作 1 1 1 结束后,序列为 130 140 150 130\\ 140\\ 150 130 140 150,不存在逆序对;
操作 2 2 2 结束后,序列为 150 140 130 150\\ 140\\ 130 150 140 130, ( 1 , 2 ) (1,2) (1,2), ( 1 , 3 ) (1,3) (1,3), ( 2 , 3 ) (2,3) (2,3) 共 3 3 3 对逆序对。
Solution
我们先对原序列使用树状数组求一次逆序对,然后考虑修改操作直接在原答案上进行更新维护答案。
考虑每次交换元素 a l a_l al 与 a r a_r ar 时对答案的影响。
逆序对实际上是就是下标小于自己的元素中权值大于自己的数的个数,显然交换 l , r l,r l,r 之后, a l , a r a_l,a_r al,ar 与区间 [ 1 , l ) [1,l) [1,l)、 ( r , n ] (r,n] (r,n] 中的元素相对关系保持不变,答案无影响。
考虑交换操作对区间 ( l , r ) (l,r) (l,r) 内元素 a i a_i ai 的逆序对造成的影响
-
a i > a l → a n s + 1 a_i>a_l\\rightarrow ans+1 ai>al→ans+1
-
a i < a l → a n s − 1 a_i<a_l\\rightarrow ans-1 ai<al→ans−1
-
a i > a r → a n s − 1 a_i>a_r\\rightarrow ans-1 ai>ar→ans−1
-
a i < a r → a n s + 1 a_i<a_r\\rightarrow ans+1 ai<ar→ans+1
-
a l > a r → a n s − 1 a_l>a_r\\rightarrow ans-1 al>ar→ans−1
-
a l < a r → a n s + 1 a_l<a_r\\rightarrow ans+1 al<ar→ans+1
我们在使用树状数组计算逆序对的时候由于一维树状数组只有 v a l & c n t \\mathrm{val}\\ \\&\\ \\mathrm{cnt} val & cnt ,仅维护序列前缀和, 并没有序列下标顺序这一维度,所以需要我们倒序循环来保证 j < i j<i j<i 这一条件。我们这里动态维护的时候,考虑涉及到的需要修改的区间 ( l , r ) (l,r) (l,r),并人为地维护顺序这一信息保证满足逆序对的条件 j < i A N D a j > a i j<i\\ \\mathrm{AND}\\ a_j>a_i j<i AND aj>ai 。我们可以使用平衡树来维护顺序这一维度,但是由于本题数据较小, n ≤ 2 × 1 0 4 n\\le 2\\times 10^4 n≤2×104,考虑可以直接暴力分块。我们将序列分块,然后在每一个块内离散化后建一个树状数组 v a l & c n t \\mathrm{val}\\ \\&\\ \\mathrm{cnt} val & cnt 维护小于自己的数的个数。分块维护序列,在区间 [ l + 1 , r − 1 ] [l+1,r-1] [l+1,r−1] 内的整块,我们每次直接 O ( log n ) O(\\log n) O(lo以上是关于BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ 2141][国家集训队 2011]排队 树状数组套平衡树