自己的做法有点奇怪,参考了区间逆序对的做法。
设一个询问的矩形为((p1,p2),(p3,p4))
定义(g(i,j))为顶部为(i),右部为(j),左/底部贴着平面的最左/最下边的答案
由于问题比区间逆序对强,所以考虑分块。
在分块时,序列被分为了(L,M,R)三个部分,(L,R)是左,右散块,(M)是中间整块。
每个点的贡献是以它为左下角的矩形和询问矩形的交。
(L,R)的贡献可以枚举(L)的每个节点,这样子贡献就是(R)平面上的一个子平面。
把每个块内的(a)离散化后显然可以二维前缀和。
为了避免二分,每个块(i)需要维护(f_{i,j})表示第(i)个块内小于(j)的最大数的排名。
(L,M)和(M,R)的贡献是对称的,所以只需要处理(L,M)的贡献。
二维前缀和后,转化成了计算顶部任意,右部贴着某个块,左/底部贴着平面的最左/最下边的答案。
设(s_{i,j})表示右部为第(i)个块的右端点,顶部为(j)的答案,显然可以把前(i)个块内的点排序后求。
(M)内部的每个节点的贡献可以被拆成在块内,块外的。
块内的贡献事实上就是求块内的纵坐标在查询下界,上界的点的逆序对个数。
一个块内最多只有(sqrt{n}*sqrt{n}=n)类贡献,可以通过前面的二维前缀和,枚举左端点,右端点递增处理。
找下界,上界在这个块内对应的贡献类型可以用前面提到的(f)。
设当前最右的整块的右部横坐标为(p)
设当前考虑的节点为(i),(i)所在块的右部横坐标为(q),扫描(M)的整块做处理。则我们要求矩形([(q,a_i+1),(p,p4)])内的点数。
二维差分后变成(g(p,p4)-g(p,a_i)-g(q,p4)+g(q,a_i))。
(g(p,p4))和(g(q,p4))贡献和(i)无关,显然可以用前面提到的二维前缀和求出(i)的个数。
由于(p4)贴在块的右端点上,所以可以用前面提到的(s)求。
(g(i,a_i))可以在块内维护一个前缀和(t),(t_i)表示(g(i,a_i)),找标号可以用以前的数组(f)。
(g(q,a_i))可以把这个块挂在(q)的块上。
这事实上是一些点有权值,要求一个左部贴着某个块的左部,右部贴着某个块的右部平面的点的权值和。
由于矩形贴在块的右端点上,所以可以用前面提到的(s)求。
可以给每个块再维护一个前缀和,然后扫描每个当前询问包含的块,用(f)内的数组求出标号后用前缀和求出答案。
时间复杂度(O((n+m)sqrt{n})),感觉常数很大。