SDOI2017 相关分析
SDOI2017 相关分析
题意:
题解:
看了\(loj\) 300多份代码,似乎我是唯二写分块的?刚开始感觉线段树比较难写,就开始码分块了。现在知道为什么没人写分块了……
很容易想到将式子进行拆分,然后维护各种东西:
操作1:\(a = \frac{\sum_{i = L}^{R}(x_i * y_i + x_i * \overline{y} + \overline{x} * y_i + \overline{x} * \overline{y})}{\sum_{i = L}^R(x_i^2 + \overline{x}^2 - 2 * x_i * \overline{x})}\),这个可以通过维护区间\(x_i,y_i\)的和,\(x_i * y_i\)的和来计算。
操作2:\(\forall_{L \leq i \leq R} (x_i, y_i) \to (x_i + S, y_i + T)\),这个修改是比较容易的,边角块暴力解决,中间块打标记之后更新区间\(x_i, y_i, x_i * y_i\)的和,具体方法就是吧公式暴力拆开就行了。
操作3:\(\forall_{L \leq i \leq R} (x_i, y_i) \to (i + S, i + T)\),这个操作相当与是区间赋值,思想还是一样的,但是唯一一个问题就是如何处理边角块暴力赋值和区间块赋值两个标记的关系。显然我们一个块上的标记是无法下传的每个元素中的,所以我们需要写一个函数来计算当前位置的\(x_i, y_i\)实际为多少。但是区间赋值和边角暴力赋值的标记又不会合并,所以我们记\(Las[i]\)表示第\(i\)个数上一次修改的时间,\(las[i]\)表示第\(i\)个块上一次修改的时间,这样我们可以通过比较\(Las[i]\)和\(las[bl[i]]\)的值来判断是以边角暴力赋的值为准还是整块赋值为准。之后就没什么了。
Code
啊这代码真胖……
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 500;
const int Sq = 1e3 + 50;
const double inf = 1e16;
int n, m, B, cb, T;
double X[N], Y[N], XY[Sq], SX[Sq], SY[Sq], XX[Sq], tagX[Sq], tagY[Sq], CX[Sq], CY[Sq], Sum2[N], las[N], Las[N], TagX[N], TagY[N];
int bl[N];
double True(int x, int tp) {
int bc = bl[x];
double ret;
if(tp == 1) {
if(CX[bc] < inf) ret = CX[bc] + x;
else ret = X[x];
ret += tagX[bc];
if(Las[x] >= las[bc]) ret += TagX[x];
else TagX[x] = 0;
}
else {
if(CY[bc] < inf) ret = CY[bc] + x;
else ret = Y[x];
ret += tagY[bc];
if(Las[x] >= las[bc]) ret += TagY[x];
else TagY[x] = 0;
}
return ret;
}
void Modify1(int l, int r, double s, double t) {
if(bl[l] == bl[r]) {
for(int i = l; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s, TagY[i] += t;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
return ;
}
int LB = bl[l], RB = bl[r];
for(int i = l; i <= LB * B; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s, TagY[i] += t;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
for(int i = (RB - 1) * B + 1; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s, TagY[i] += t;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
for(int i = LB + 1; i <= RB - 1; i++) {
int ll = (i - 1) * B + 1, rr = i * B;
double nwxy = XY[i] + B * s * t + s * SY[i] + t * SX[i], nwxx = XX[i] + B * s * s + s * SX[i] * 2;
double nwsx = SX[i] + s * B, nwsy = SY[i] + t * B;
XY[i] = nwxy, XX[i] = nwxx, SX[i] = nwsx, SY[i] = nwsy; tagX[i] += s, tagY[i] += t;
}
return ;
}
void Modify2(int l, int r, double s, double t) {
if(bl[l] == bl[r]) {
for(int i = l; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s + i - nwx, TagY[i] += t + i - nwy;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
return ;
}
int LB = bl[l], RB = bl[r];
for(int i = l; i <= LB * B; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s + i - nwx, TagY[i] += t + i - nwy;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
for(int i = (RB - 1) * B + 1; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] -= nwx, SY[bl[i]] -= nwy; XX[bl[i]] -= nwx * nwx, XY[bl[i]] -= nwx * nwy;
Las[i] = T;
TagX[i] += s + i - nwx, TagY[i] += t + i - nwy;
nwx = True(i, 1), nwy = True(i, 2);
SX[bl[i]] += nwx, SY[bl[i]] += nwy; XX[bl[i]] += nwx * nwx, XY[bl[i]] += nwx * nwy;
}
for(int i = LB + 1; i <= RB - 1; i++) {
int ll = (i - 1) * B + 1, rr = i * B;
double nwxy = s * t * B + (s + t) * (ll + rr) / 2.0 * B + Sum2[rr] - Sum2[ll - 1];
double nwxx = s * s * B + Sum2[rr] - Sum2[ll - 1] + s * (ll + rr) * B;
double nwsx = s * B + (ll + rr) / 2.0 * B, nwsy = t * B + (ll + rr) / 2.0 * B;
XY[i] = nwxy, XX[i] = nwxx, SX[i] = nwsx, SY[i] = nwsy; tagX[i] = 0, tagY[i] = 0, CX[i] = s, CY[i] = t; las[i] = T;
}
return ;
}
double Query(int l, int r) {
if(bl[l] == bl[r]) {
double sumxy = 0.0, sumxx = 0.0, sumx = 0.0, sumy = 0.0;
for(int i = l; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
sumxy += nwx * nwy; sumx += nwx, sumy += nwy; sumxx += nwx * nwx;
}
double _x = sumx / (double)(r - l + 1), _y = sumy / (double)(r - l + 1);
double ret = sumxy - sumy * _x;
ret /= (double)(sumxx - _x * sumx);
return ret;
}
int LB = bl[l], RB = bl[r];
double sumxy = 0.0, sumxx = 0.0, sumx = 0.0, sumy = 0.0;
for(int i = l; i <= LB * B; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
sumxy += nwx * nwy; sumx += nwx, sumy += nwy; sumxx += nwx * nwx;
}
for(int i = (RB - 1) * B + 1; i <= r; i++) {
double nwx = True(i, 1), nwy = True(i, 2);
sumxy += nwx * nwy; sumx += nwx, sumy += nwy; sumxx += nwx * nwx;
}
for(int i = LB + 1; i <= RB - 1; i++) {
sumxy += XY[i], sumx += SX[i], sumy += SY[i], sumxx += XX[i];
}
double _x = sumx / (double)(r - l + 1), _y = sumy / (double)(r - l + 1);
double ret = sumxy - sumy * _x;
ret /= (double)(sumxx - _x * sumx);
return ret;
}
int main() {
scanf("%d%d", &n, &m); B = sqrt(n) / 2; B = max(B, 1);
for(int i = 1; i <= n; i++) Sum2[i] = Sum2[i - 1] + (double)i * i;
for(int i = 1; i <= n; i++) scanf("%lf", &X[i]);
for(int i = 1; i <= n; i++) scanf("%lf", &Y[i]);
for(int i = 1; i <= n; i++) {
bl[i] = (i - 1) / B + 1;
XY[bl[i]] += X[i] * Y[i]; XX[bl[i]] += X[i] * X[i]; SX[bl[i]] += X[i]; SY[bl[i]] +=Y[i];
}
cb = bl[n];
for(int i = 1; i <= cb; i++) CX[i] = CY[i] = inf;
while(m--) {
++T;
int tp, l, r;
double s, t;
scanf("%d%d%d", &tp, &l, &r);
if(tp == 1) {
double ret = Query(l, r);
printf("%.6f\n", ret);
}
else if(tp == 2) {
scanf("%lf%lf", &s, &t);
Modify1(l, r, s, t);
}
else {
scanf("%lf%lf", &s, &t);
Modify2(l, r, s, t);
}
}
return 0;
}