三维偏序问题:
每个元素有3个属性,a,b,c。
求解对于每个
i
i
i,
a
j
<
a
i
且
b
j
<
b
i
且
c
j
<
c
i
a_j<a_i且b_j<b_i且c_j<c_i
aj<ai且bj<bi且cj<ci的
j
j
j的数目。
solution:
一维偏序直接排序
二维偏序先按照一维排序,再记录一个树状数组。
三维偏序先按照第一维排序。然后分治; 左右两边分别按照
y
y
y来排序。这样仍然可以保证分治的左右两边依然满足
a
l
e
f
t
<
a
r
i
g
h
t
a_{left}<a_{right}
aleft<aright。 这个时候归并,
i
i
i从左端点到
m
i
d
mid
mid,
j
j
j从
m
i
d
+
1
mid+1
mid+1到
r
r
r。 对于每个固定的
j
j
j,移动合法的
i
i
i并把它加入树状数组。统计答案。注意每次做完之后,要把加入树状数组的那些位置再减回去。
注意点:
1:每次做完之后,要把加入树状数组的位置减回去。(实际上也已经清空了)
2:如果一开始有
a
,
b
,
c
a,b,c
a,b,c三个属性完全相同的点。把它们缩成一个点再做。最后答案加上
c
n
t
−
1
cnt-1
cnt−1(如果是<=的话)。 原因是属性相同的点,计算贡献会出现混乱。
3:注意算贡献的话,ans是
+
=
+=
+=,因为它可能会被多次统计贡献!!!
4:注意一开始合并属性相同的点时,要在最后一个同样点的时候加入。否则w里面就都是1了。!!
luoguP3810 板子
loj2056
1:在线转离线。我们把这个动态的操作看成静态。仍然考虑用dp来求LIS。
f[i] = max(f[j]) + 1(j<i,a[j] <= mn[i], mx[j] <= a[i]) (因为同一时刻只会有1个变化)
这就转化为一个dp问题。我们只需要满足这些限制。
①:从左向右扫,满足限制1。插入点(mx[j], a[j])。 转移就看一个矩阵内点的最大值。采用树套树维护。O(nlog^2)
②:cdq分治+树状数组。先递归slove(l, mid);计算左边对右边的转移。我们把左边按照a排序,右边按照mn排序。用双指针维护对于右边每个数的合法左边区间。把左边mx[]处插入f值。转移就是查询前缀最大值。里面写一个树状数组就好了。O(nlog^2)
总结:
1:偏序问题不一定三维要完全对应。
2: 在满足一定条件限制下计算最大值可以考虑偏序问题。
3:注意递归顺序是先求左半边,再算左对右的贡献,再求右半边。因为dp转移的顺序是要从左到右的。
4:这个树状数组里面求前缀最大值,操作完后要直接清空了。(记录修改位置,和0取min也行吧)
5:注意排过序后里面原来的下标就变掉了!要用索引排序。记录这个位置所对应的原下标,在那上面操作。 如果不这样做,需要还原[mid +1, r] 这个区间。