相关分析 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 }
posted @ 2017-04-24 17:24  草根柴鸡  阅读(277)  评论(0编辑  收藏  举报