相关分析 BZOJ 4821
相关分析
【问题描述】
Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度、颜色等等,进而估算出星星的距离,半径等等。Frank不仅喜欢观测,还喜欢分析观测到的数据。他经常分析两个参数之间(比如亮度和半径)是否存在某种关系。现在Frank要分析参数X与Y之间的关系。他有n组观测数据,第i组观测数据记录了x_i和y_i。他需要一下几种操作1 L,R:用直线拟合第L组到底R组观测数据。用xx表示这些观测数据中x的平均数,用yy表示这些观测数据中y的平均数,即
xx=Σx_i/(R-L+1)(L<=i<=R)
yy=Σy_i/(R-L+1)(L<=i<=R)
如果直线方程是y=ax+b,那么a应当这样计算:
a=(Σ(x_i-xx)(y_i-yy))/(Σ(x_i-xx)(x_i-xx)) (L<=i<=R)
你需要帮助Frank计算a。
2 L,R,S,T:
Frank发现测量数据第L组到底R组数据有误差,对每个i满足L <= i <= R,x_i需要加上S,y_i需要加上T。
3 L,R,S,T:
Frank发现第L组到第R组数据需要修改,对于每个i满足L <= i <= R,x_i需要修改为(S+i),y_i需要修改为(T+i)。
【输入格式】
第一行两个数n,m,表示观测数据组数和操作次数。
接下来一行n个数,第i个数是x_i。
接下来一行n个数,第i个数是y_i。
接下来m行,表示操作,格式见题目描述。
1<=n,m<=10^5,0<=|S|,|T|,|x_i|,|y_i|<=10^5
保证1操作不会出现分母为0的情况。
【输出格式】
对于每个1操作,输出一行,表示直线斜率a。
选手输出与标准输出的绝对误差不超过10^-5即为正确。
【样例输入】
3 5
1 2 3
1 2 3
1 1 3
2 2 3 -3 2
1 1 2
3 1 2 2 1
1 1 3
【样例输出】
1.0000000000
-1.5000000000
-0.6153846154
题解:
对于线性回归方程我们把它拆分,x平方和,x权值和,y权值和,xy权值和,x平方和
第二个第三个操作用初中学的完全平方公式拆一拆就好了
记得爆 long long MMP
1 #include<cmath> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 inline void Scan(int &x) 9 { 10 char c; 11 bool o = false; 12 while(!isdigit(c = getchar())) 13 if(c == '-') 14 o = true; 15 x = c - '0'; 16 while(isdigit(c = getchar())) 17 x = x * 10 + c - '0'; 18 if(o) x = -x; 19 } 20 const int maxn = 1e5 + 1; 21 const int maxs = maxn << 2; 22 struct ele 23 { 24 long long x, y; 25 double xy, sx; 26 inline void print() 27 { 28 printf("%lf %lf %lf %lf\n", (double) x, (double) y, (double) xy, (double) sx); 29 } 30 inline void empty() 31 { 32 x = y = xy = sx = 0; 33 } 34 }; 35 struct tag 36 { 37 long long s, t; 38 inline bool exist() 39 { 40 return s || t; 41 } 42 inline void empty() 43 { 44 s = t = 0; 45 } 46 }; 47 tag mark[maxs], sign[maxs]; 48 ele ans, add; 49 ele tr[maxs]; 50 int n, m; 51 int x[maxn], y[maxn]; 52 double sum[maxn]; 53 inline ele operator + (ele a, ele b) 54 { 55 return (ele) {a.x + b.x, a.y + b.y, a.xy + b.xy, a.sx + b.sx}; 56 } 57 inline tag operator + (tag a, tag b) 58 { 59 return (tag) {a.s + b.s, a.t + b.t}; 60 } 61 void Build(int k, int l, int r) 62 { 63 if(l == r) 64 { 65 tr[k] = (ele) {x[l], y[l], (double) x[l] * y[l], (double) x[l] * x[l]}; 66 return; 67 } 68 int mi = l + r >> 1; 69 int lc = k << 1, rc = k << 1 | 1; 70 Build(lc, l, mi), Build(rc, mi + 1, r); 71 tr[k] = tr[lc] + tr[rc]; 72 } 73 inline void Add(int k, int n, long long s, long long t) 74 { 75 long long x, y; 76 double xy, sx; 77 x = n * s; 78 y = n * t; 79 xy = (double) s * tr[k].y + (double) t * tr[k].x + (double) n * s * t; 80 sx = (double) n * s * s + 2 * s * (double) tr[k].x; 81 add = (ele) {x, y, xy, sx}; 82 tr[k] = tr[k] + add; 83 mark[k] = mark[k] + (tag) {s, t}; 84 } 85 inline long long Sum(long long l, long long r, int n) 86 { 87 return (l + r) * n / 2; 88 } 89 inline void Change(int k, double s, double t, int l, int r) 90 { 91 int n = r - l + 1; 92 double x, y, xy, sx; 93 x = Sum(s + l, s + r, n); 94 y = Sum(t + l, t + r, n); 95 xy = (double) n * s * t + (double) (s + t) * Sum(l, r, n) + sum[r] - sum[l - 1]; 96 sx = (double) n * s * s + sum[r] - sum[l - 1] + (double) 2 * s * Sum(l, r, n); 97 tr[k] = (ele) {x, y, xy, sx}; 98 sign[k] = (tag) {s, t}; 99 mark[k].empty(); 100 } 101 inline void Down(int k, int l, int r) 102 { 103 int lc = k << 1, rc = k << 1 | 1; 104 int mi = l + r >> 1; 105 double s, t; 106 if(sign[k].exist()) 107 { 108 s = sign[k].s, t = sign[k].t; 109 Change(lc, s, t, l, mi), Change(rc, s, t, mi + 1, r); 110 sign[k].empty(); 111 } 112 if(mark[k].exist()) 113 { 114 s = mark[k].s, t = mark[k].t; 115 Add(lc, mi - l + 1, s, t), Add(rc, r - mi, s, t); 116 mark[k].empty(); 117 } 118 } 119 void Query(int k, int l, int r, int x, int y) 120 { 121 if(x <= l && r <= y) 122 { 123 ans = ans + tr[k]; 124 return; 125 } 126 Down(k, l, r); 127 int mi = l + r >> 1; 128 if(x <= mi) Query(k << 1, l, mi, x, y); 129 if(y > mi) Query(k << 1 | 1, mi + 1, r, x, y); 130 } 131 void Insert(int k, int l, int r, int x, int y, int s, int t) 132 { 133 if(x <= l && r <= y) 134 { 135 Add(k, r - l + 1, s, t); 136 return; 137 } 138 Down(k, l, r); 139 int mi = l + r >> 1; 140 int lc = k << 1, rc = k << 1 | 1; 141 if(x <= mi) Insert(lc, l, mi, x, y, s, t); 142 if(y > mi) Insert(rc, mi + 1, r, x, y, s, t); 143 tr[k] = tr[lc] + tr[rc]; 144 } 145 void Modify(int k, int l, int r, int x, int y, int s, int t) 146 { 147 if(x <= l && r <= y) 148 { 149 Change(k, s, t, l, r); 150 return; 151 } 152 Down(k, l, r); 153 int mi = l + r >> 1; 154 int lc = k << 1, rc = k << 1 | 1; 155 if(x <= mi) Modify(lc, l, mi, x, y, s, t); 156 if(y > mi) Modify(rc, mi + 1, r, x, y, s, t); 157 tr[k] = tr[lc] + tr[rc]; 158 } 159 int main() 160 { 161 Scan(n), Scan(m); 162 for(int i = 1; i <= n; ++i) Scan(x[i]); 163 for(int i = 1; i <= n; ++i) Scan(y[i]); 164 for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + (double) i * i; 165 Build(1, 1, n); 166 int o, x, y, s, t; 167 int len; 168 long long meanx; 169 long double up, down, meany; 170 while(m--) 171 { 172 Scan(o), Scan(x), Scan(y); 173 switch(o) 174 { 175 case 1: 176 { 177 ans.empty(); 178 Query(1, 1, n, x, y); 179 len = y - x + 1; 180 meanx = ans.x; 181 meany = (double) ans.y / len; 182 up = ans.xy - meanx * meany; 183 down = ans.sx - (double) meanx * meanx / len; 184 double answer = up / down; 185 printf("%.10lf\n", answer); 186 break; 187 } 188 case 2: 189 { 190 Scan(s), Scan(t); 191 Insert(1, 1, n, x, y, s, t); 192 break; 193 } 194 case 3: 195 { 196 Scan(s), Scan(t); 197 Modify(1, 1, n, x, y, s, t); 198 break; 199 } 200 } 201 } 202 }