首页 > 代码库 > Bestcoder7(1004)hdu4988(经典问题:树状数组套treap求解动态逆序对)
Bestcoder7(1004)hdu4988(经典问题:树状数组套treap求解动态逆序对)
Little Pony and Boast Busters
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 83 Accepted Submission(s): 32
Problem Description
"I hereby challenge you, Ponyvillians: anything you can do, I can do better. Any takers? Anyone? Or is Trixie destined to be the greatest equine who has ever lived!?!" — "Boast Busters"
Given two permutation P0 && P1 of {0, 1, ..., n - 1}, we define the crossing number of it as follows. Write P0 from left to right above P1 and draw a straight line between each same elements. The crossing number of P0 and P1 is the number of pairs of lines that cross.
For example, if n = 5, and P0 = {0, 1, 2, 3, 4}, and P1 = {1, 3, 0, 2, 4}, then the crossing number of P0 and P1 is 3, as shown in the figure below.
Now given you the two permutation, you need to implement the following operations:
SWAP p a b: swap Pp[a] and Pp[b] (0<=p<=1, 0<=a, b<=n-1).
QUERY: ask the crossing number of the current P0 and P1.
Given two permutation P0 && P1 of {0, 1, ..., n - 1}, we define the crossing number of it as follows. Write P0 from left to right above P1 and draw a straight line between each same elements. The crossing number of P0 and P1 is the number of pairs of lines that cross.
For example, if n = 5, and P0 = {0, 1, 2, 3, 4}, and P1 = {1, 3, 0, 2, 4}, then the crossing number of P0 and P1 is 3, as shown in the figure below.
Now given you the two permutation, you need to implement the following operations:
SWAP p a b: swap Pp[a] and Pp[b] (0<=p<=1, 0<=a, b<=n-1).
QUERY: ask the crossing number of the current P0 and P1.
Input
Input contains multiple test cases (less than 10). For each test case, the first line contains one integer n (1<=n<=10^5).
The second line contains n integers P0[0], P0[1], ..., P0[n-1].
The third line contains n integers P1[0], P1[1], ..., P1[n-1].
The next line contains one integer q —— the number of operations (1<=q<=10^5). The next q line, each line will contains a operation as we mentioned above.
The second line contains n integers P0[0], P0[1], ..., P0[n-1].
The third line contains n integers P1[0], P1[1], ..., P1[n-1].
The next line contains one integer q —— the number of operations (1<=q<=10^5). The next q line, each line will contains a operation as we mentioned above.
Output
For each query, output the corresponding result in one line.
Sample Input
5 0 1 2 3 4 1 3 0 2 4 5 QUERY SWAP 1 2 4 QUERY SWAP 0 2 4 QUERY
Sample Output
3 6 5
Source
BestCoder Round #7
题意:给出两个0到n-1的排列,然后支持两种操作,QUERY查询两组排列的交叉的元素个数,SWAP 交换一个排列中两个位置的元素
思路:这题最后可以转化为给出一个排列P(将给出的两个排列的位置一一对应起来,参见大神的题解http://bestcoder.hdu.edu.cn),
可以动态交换P的任意两个位置的数,然后查询整个序列的逆序对数
动态逆序对是比较经典的树套树模型,我这里用的是树状数组套treap实现的,之前用的线段树妥妥的超时了
可以先用树状或归并排序求出初始序列的逆序对数,记为ans,然后每次查询只需要输出ans即可
重点在于交换,因为交换以后ans会随之改变,假设现在要交换L,R位置的数,那么[0,L-1],[R+1,n-1]这些位置的数是不用考虑的,因为它们对中间
元素的逆序对的贡献是不会改变的,所以只用考虑[L+1,R-1]之间的数
假设元素P[L] > P[R] ,设区间[L+1,R-1]的数小于P[L]的个数为L1,大于的个数为L2,同理设小于P[R]的个数为R1,大于的个数为R2,那么交换后的
答案 为ans = ans + L2-L1 + R1-R2 = ans + R1+L2 - (L1+R2),现在只需求出 R1 + L2 问题即可完美解决,因为L1+R2=2*n-(R1+L2) ,其中n为区间
[L+1,R-1]的元素个数,现在令区间[L+1,R-1]为S
而求R1等价于求S中元素小于P[R]的个数,求L2等价于求S中元素大于P[L]的个数,所以只需要在树状数组里套一个treap,用来维护该树状数组管辖的
区间的元素,具体涉及两种操作:
1.交换元素,相当于先将原位置的数删除,再在新的位置插入,这个就是树状数组单点更新了
2.查询一段区间中所有小于(大于)x的元素个数,相当于区间求和
怎么样,难点全部攻破了吧,这题也是把我写的醉到不行,调了许久才发现竟然树状数组没有初始化,sad~,累觉不爱,可以睡觉去了
<script src="https://code.csdn.net/snippets/464352.js" type="text/javascript"></script>
Bestcoder7(1004)hdu4988(经典问题:树状数组套treap求解动态逆序对)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。