五种操作都是仿射变换。如果我们能维护一个区间内所有
x,y,x2,y2 的和,我们就能轻松回答第六和第七种操作。把仿射变换矩阵写出来:
x′y′1=ad0be0cf1xy1
展开后可以得到:
{x′=ax+by+cy′=dx+ey+f
遇到区间操作,考虑扔到线段树上去维护。懒标记线段树需要分析三点:节点和节点合并、标记和标记合并、节点和标记合并。节点信息维护
∑i=1nxi,∑i=1nyi,∑i=1nxi2,∑i=1nyi2,∑i=1nxiyi。懒标记维护仿射变换矩阵中的
a,b,c,d,e,f,其幺元即为对角矩阵(
a=1,b=0,c=0,d=0,e=1,f=0)。
节点和节点用脚合并,直接加起来就行。
标记和标记合并即将两个矩阵相乘。注意我使用的列矩阵,所以后来的标记
V 应该左乘到矩阵
U 上:
VaVd0VbVe0VcVf1UaUd0UbUe0UcUf1=UaVa+UdVbUaVd+UdVe0UbVa+UeVbUbVd+UeVe0UcVa+UfVb+VcUcVd+UfVe+Vf1
最后考虑如何合并信息与标记。
⎩⎨⎧∑i=1nxi′∑i=1nyi′∑i=1nxi′2∑i=1nyi′2∑i=1nxiyi=========∑i=1n(axi+byi+c)=a∑i=1nxi+b∑i=1nyi+cn∑i=1n(dxi+eyi+c)=d∑i=1nxi+e∑i=1nyi+fn∑i=1n(axi+byi+c)2=∑i=1n(a2xi2+b2yi2+c2+2abxiyi+2acxi+2bcyi)a2∑i=1nxi2+b2∑i=1nyi2+c2n+2ab∑i=1nxiyi+2ac∑i=1nxi+2bc∑i=1nyi∑i=1n(dxi+eyi+f)2=∑i=1n(d2xi2+e2yi2+c2+2dexiyi+2dfxi+2efyi)d2∑i=1nxi2+e2∑i=1nyi2+f2n+2de∑i=1nxiyi+2df∑i=1nxi+2ef∑i=1nyi∑i=1n(axi+byi+c)(dxi+eyi+f)∑i=1n(adxi2+beyi2+cf+(ae+bd)xiyi+(af+cd)xi+(bf+ce)yi)ad∑i=1nxi2+be∑i=1nyi2+cfn+(ae+bd)∑i=1nxiyi+(af+cd)∑i=1nxi+(bf+ce)∑i=1nyi
数据结构部分也就做完了。再讨论一下五种操作。注意以下矩阵都是左乘的,需要从右往左读。你也不需要实际计算出这些结果,按照顺序在线段树上依次操作即可。
{x′=x+ay′=b+b
可知
Aa=1,Ab=0,Ac=a,Ad=0,Ae=1,Af=b。因此
A=100010ab1
绕点旋转:平移两点,使得旋转中心与原点重合。此时绕原点旋转,是线性变换。再平移回去即可。
100010ab1cosθsinθ0−sinθcosθ0001100010−a−b1
以点为中心缩放:同理,转化为按原点为中心缩放的线性变化问题。
100010ab1λ000λ0001100010−a−b1
轴对称:向下平移
b,再绕原点顺时针旋转
θ,此时对称轴变为
x 轴,
y 坐标乘
−1 即可。然后再倒腾回去。
1000100y01cosθsinθ0−sinθcosθ00011000−10001cos(−θ)sin(−θ)0−sin(−θ)cos(−θ)00011000100−y01
投影:同理,转化为投影到
x 轴,
y 坐标乘
0 即可。再倒腾回去。
1000100y01cosθsinθ0−sinθcosθ0001100000001cos(−θ)sin(−θ)0−sin(−θ)cos(−θ)00011000100−y01
还有两种询问。
询问 6:输出
m1∑i=1mxi 与
m1∑i=1myi。
询问 7:输出
i=1∑m((xi−a)2+(yi−b)2)=i=1∑m(xi2−2xia+a2+yi2−2yib+b2)=i=1∑mxi2−2ai=1∑mxi+ma2+i=1∑myi2−2bi=1∑myi+mb2