题目
选取显像管的任意一个平面,一开始平面内有
n
n
n个电子,初始速度分别为
v
i
v_i
vi,定义飘升系数为:
∑
1
≤
i
≤
j
≤
n
∣
v
i
×
v
j
∣
2
(
×
表
示
叉
乘
)
\sum_{1\leq i \leq j \leq n} |v_i \times v_j|^2(\times表示叉乘)
1≤i≤j≤n∑∣vi×vj∣2(×表示叉乘)
电子的速度常常会发生变化。也就是说,有两种类型的操作:
• 1 p x y 1\ \ p\ \ x\ \ y 1 p x y将 p p p 改为 ( x , y ) (x,\ y) (x, y);
• 2 l r 2\ \ l\ \ r 2 l r询问 [ l , r ] [l, r] [l,r] 这段区间内的电子的飘升系数。
答案对 20170927 20170927 20170927 取模即可。
Solution
观察答案并推导:
a
n
s
=
∑
1
≤
i
<
j
≤
n
(
x
i
y
j
−
x
j
y
i
)
2
=
∑
1
≤
i
<
j
≤
n
x
i
2
y
j
2
+
∑
1
≤
i
<
j
≤
n
x
j
2
y
i
2
−
2
∑
1
≤
i
<
j
≤
n
x
i
x
j
y
i
y
j
=
∑
1
≤
i
,
j
≤
n
[
i
≠
j
]
x
i
2
y
j
2
−
∑
1
≤
i
,
j
≤
n
[
i
≠
j
]
(
x
i
y
i
⋅
x
j
y
j
)
=
(
∑
i
=
1
n
x
i
2
⋅
∑
i
=
1
n
y
i
2
−
∑
i
=
1
n
(
x
i
2
y
i
2
)
)
−
(
∑
i
=
1
n
x
i
y
i
⋅
∑
i
=
1
n
x
i
y
i
−
∑
i
=
1
n
(
x
i
y
i
)
2
)
=
∑
i
=
1
n
x
i
2
⋅
∑
i
=
1
n
y
i
2
−
(
∑
i
=
1
n
x
i
y
i
)
2
\begin{aligned} ans\ &= \sum_{1 \leq i < j \leq n} \mathrm{(x_iy_j - x_jy_i)^2} \\ &=\sum_{1 \leq i < j \leq n} \mathrm{x_i^2y_j^2} + \sum_{1 \leq i < j \leq n} \mathrm{x_j^2y_i^2} - 2\sum_{1 \leq i < j \leq n}\mathrm{x_ix_jy_iy_j}\\ &=\sum_{1 \leq i, j \leq n}\mathrm{[i ≠j]x_i^2y_j^2} - \sum_{1 \leq i,j \leq n}\mathrm{[i ≠ j] (x_iy_i \cdot x_jy_j)} \\ &= (\sum_{i = 1}^{n}x_i^2 \cdot \sum_{i = 1}^{n}y_i^2 - \sum_{i = 1}^{n}(x_i^2y_i^2) )- (\sum_{i = 1}^{n} x_iy_i \cdot \sum_{i = 1}^{n}x_iy_i - \sum_{i = 1}^{n}(x_iy_i)^2) \\ &=\sum_{i = 1}^{n}x_i^2 \cdot \sum_{i = 1}^{n}y_i^2 - (\sum_{i = 1}^{n} x_iy_i)^2 \end{aligned}
ans =1≤i<j≤n∑(xiyj−xjyi)2=1≤i<j≤n∑xi2yj2+1≤i<j≤n∑xj2yi2−21≤i<j≤n∑xixjyiyj=1≤i,j≤n∑[i=j]xi2yj2−1≤i,j≤n∑[i=j](xiyi⋅xjyj)=(i=1∑nxi2⋅i=1∑nyi2−i=1∑n(xi2yi2))−(i=1∑nxiyi⋅i=1∑nxiyi−i=1∑n(xiyi)2)=i=1∑nxi2⋅i=1∑nyi2−(i=1∑nxiyi)2
三个树状数组维护三个值
∑
i
=
1
n
x
i
2
\sum_{i = 1}^n x_i^2
∑i=1nxi2 、
∑
i
=
1
n
y
i
2
\sum_{i = 1}^n y_i^2
∑i=1nyi2 、
∑
i
=
1
n
x
i
y
j
\sum_{i = 1}^nx_iy_j
∑i=1nxiyj,三个值。这样就可以支持修改操作并快速维护答案了。
C o d e : \mathrm{Code:} Code:
#include <bits/stdc++.h>
#define N 1000110
#define mod 20170927
using namespace std;
int n, m;
inline int add(int a, int b) {
if (b < 0)
return (a + b < 0 ? a + b + mod : a + b);
else
return (a + b >= mod ? a + b - mod : a + b);
}// add函数把加减写一起
inline int del(int a, int b) { return a - b < 0 ? a - b + mod : a - b; }
inline int mul(int a, int b) { return 1LL * a * b % mod; }
inline int read() {
int s = 0, w = 1;
char c = getchar();
while ((c > '9' || c < '0') && c != '-') c = getchar();
if (c == '-') w = -1, c = getchar();
while (c <= '9' && c >= '0')
s = (s << 3) + (s << 1) + c - '0', c = getchar();
return s * w;
}
void write(int x) {
if (x < 0) x = ~x + 1, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + 48);
return void();
}
struct vec {
int x, y;
vec() {}
vec(int _x, int _y) {
x = _x;
y = _y;
}
inline vec operator-() { return vec(-x, -y); }
} v[N];
struct BIT {
int a[N], b[N], c[N];
void Inc(int x, vec v, int w) { //w为加&减的处理。
for (; x <= n; x += x & (-x)) {
a[x] = add(a[x], w * mul(v.x, v.x));
b[x] = add(b[x], w * mul(v.y, v.y));
c[x] = add(c[x], w * mul(v.x, v.y));
}
}
int aska(int x) {
int sum = 0;
for (; x; x -= x & (-x)) sum = add(sum, a[x]);
return sum;
}
int askb(int x) {
int sum = 0;
for (; x; x -= x & (-x)) sum = add(sum, b[x]);
return sum;
}
int askc(int x) {
int sum = 0;
for (; x; x -= x & (-x)) sum = add(sum, c[x]);
return sum;
}
int Ask(int l, int r) {
int s1 = del(aska(r), aska(l - 1));
int s2 = del(askb(r), askb(l - 1));
int s3 = del(askc(r), askc(l - 1));
return del(mul(s1, s2), mul(s3, s3));
}
} B;
signed main() {
n = read();
m = read();
for (int i = 1; i <= n; ++i) {
int x = read(), y = read();
v[i] = vec(x, y);
B.Inc(i, v[i], 1);
}
for (int i = 1; i <= m; ++i) {
int opt = read();
if (opt == 1) {
int p = read(), x = read(), y = read();
vec tmp = vec(x, y);
B.Inc(p, v[p], -1);
B.Inc(p, tmp, 1);
v[p] = tmp;
}
if (opt == 2) {
int x = read(), y = read();
write(B.Ask(x, y));
putchar(10);
}
}
return 0;
}