线段树

这题真是无聊

把式子拆开,然后可知维护xi,yi,xi^2,xi*yi,重点在于标记下传,当我们进行2号操作时,直接累加进答案和标记即可,进行3号操作时,update时先把自己这层赋值成要改变的值,再清空这层2号标记,每次pushdown把这层的下一层的标记清空,因为下一层被覆盖了,pushdown先执行3号标记,再执行2号标记,因为存在的2号标记肯定在3号标记后打的,否则肯定会被清空,所以2号标记应该在三号标记后。

而下一层的2号标记肯定是在三号标记之前打的,因为标记已经下传。

#include<bits/stdc++.h>
using namespace std;
typedef double ld;
const int N = ;
int n, m;
ld x[N], y[N];
struct node {
double sumx, sumy, sumxx, sumxy;
node(ld sumx = , ld sumy = , ld sumxx = , ld sumxy = ) : sumx(sumx), sumy(sumy), sumxx(sumxx), sumxy(sumxy) {}
void print()
{
printf("sumx=%.10f sumy=%.10f sumxx=%.10f sumxy=%.10f\n", sumx, sumy, sumxx, sumxy);
}
};
struct seg {
node tree[N << ];
ld tagx2[N << ], tagy2[N << ], tagx3[N << ], tagy3[N << ];
bool can1[N << ], can2[N << ];
ld calc(ld x)
{
return (ld)x * (ld)(x + ) * (ld)( * x + ) / ;
}
void pushdown(int o, int l, int r)
{
int mid = (l + r) >> ;
if(can1[o])
{
tree[o << ].sumx = (ld)(mid - l + ) * tagx3[o] + (ld)(mid + l) * (ld)(mid - l + ) / 2.0;
tree[o << | ].sumx = (ld)(r - mid) * tagx3[o] + (ld)(r + mid + ) * (ld)(r - mid) / 2.0;
tree[o << ].sumy = (ld)(mid - l + ) * tagy3[o] + (ld)(mid + l) * (ld)(mid - l + ) / 2.0;
tree[o << | ].sumy = (ld)(r - mid) * tagy3[o] + (ld)(r + mid + ) * (ld)(r - mid) / 2.0;
tree[o << ].sumxx = calc(tagx3[o] + mid) - calc(tagx3[o] + l - );
tree[o << | ].sumxx = calc(tagx3[o] + r) - calc(tagx3[o] + mid);
tree[o << ].sumxy = (ld)(mid - l + ) * tagx3[o] * tagy3[o] + (ld)(tagx3[o] + tagy3[o]) * (ld)(mid + l) * (ld)(mid - l + ) / 2.0 + calc(mid) - calc(l - );
tree[o << | ].sumxy = (ld)(r - mid) * tagx3[o] * tagy3[o] + (ld)(tagx3[o] + tagy3[o]) * (ld)(r + mid + ) * (ld)(r - mid) / 2.0 + calc(r) - calc(mid);
tagx3[o << ] = tagx3[o << | ] = tagx3[o];
tagy3[o << ] = tagy3[o << | ] = tagy3[o];
tagx3[o] = tagy3[o] = ;
tagx2[o << ] = tagx2[o << | ] = tagy2[o << ] = tagy2[o << | ] = ;
can2[o << ] = can2[o << | ] = ;
can1[o << ] = can1[o << | ] = can1[o];
can1[o] = ;
}
if(can2[o])
{
tree[o << ].sumxx += 2.0 * tree[o << ].sumx * tagx2[o] + (ld)(mid - l + ) * tagx2[o] * tagx2[o];
tree[o << | ].sumxx += 2.0 * tree[o << | ].sumx * tagx2[o] + (ld)(r - mid) * tagx2[o] * tagx2[o];
tree[o << ].sumxy += tree[o << ].sumx * tagy2[o] + tree[o << ].sumy * tagx2[o] + (ld)(mid - l + ) * tagx2[o] * tagy2[o];
tree[o << | ].sumxy += tree[o << | ].sumx * tagy2[o] + tree[o << | ].sumy * tagx2[o] + (ld)(r - mid) * tagx2[o] * tagy2[o];
tree[o << ].sumx += tagx2[o] * (ld)(mid - l + );
tree[o << | ].sumx += tagx2[o] * (ld)(r - mid);
tree[o << ].sumy += tagy2[o] * (ld)(mid - l + );
tree[o << | ].sumy += tagy2[o] * (ld)(r - mid);
tagx2[o << ] += tagx2[o];
tagx2[o << | ] += tagx2[o];
tagy2[o << ] += tagy2[o];
tagy2[o << | ] += tagy2[o];
tagx2[o] = ;
tagy2[o] = ;
can2[o << ] = can2[o << | ] = can2[o];
can2[o] = ;
}
}
node merge(node B, node C)
{
node A;
A.sumx = B.sumx + C.sumx;
A.sumy = B.sumy + C.sumy;
A.sumxx = B.sumxx + C.sumxx;
A.sumxy = B.sumxy + C.sumxy;
return A;
}
void build(int l, int r, int o)
{
if(l == r)
{
tree[o] = node(x[l], y[l], x[l] * x[l], x[l] * y[l]);
return;
}
int mid = (l + r) >> ;
build(l, mid, o << );
build(mid + , r, o << | );
tree[o] = merge(tree[o << ], tree[o << | ]);
}
node query(int l, int r, int o, int a, int b)
{
if(l > b || r < a) return tree[];
if(l >= a && r <= b) return tree[o];
int mid = (l + r) >> ;
pushdown(o, l, r);
node tx = query(l, mid, o << , a, b), ty = query(mid + , r, o << | , a, b);
return merge(tx, ty);
}
void update2(int l, int r, int o, int a, int b, ld s, ld t)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
tagx2[o] += s;
tagy2[o] += t;
tree[o].sumxx += 2.0 * tree[o].sumx * s + (ld)(r - l + ) * s * s;
tree[o].sumxy += t * tree[o].sumx + s * tree[o].sumy + (ld)(r - l + ) * s * t;
tree[o].sumx += (ld)(r - l + ) * s;
tree[o].sumy += (ld)(r - l + ) * t;
can2[o] = ;
return;
}
pushdown(o, l, r);
int mid = (l + r) >> ;
update2(l, mid, o << , a, b, s, t);
update2(mid + , r, o << | , a, b, s, t);
tree[o] = merge(tree[o << ], tree[o << | ]);
}
void update3(int l, int r, int o, int a, int b, ld s, ld t)
{
if(l > b || r < a) return;
if(l >= a && r <= b)
{
tagx3[o] = s;
tagy3[o] = t;
tagx2[o] = tagy2[o] = ;
tree[o].sumx = (ld)(r - l + ) * s + (ld)(l + r) * (ld)(r - l + ) / 2.0;
tree[o].sumy = (ld)(r - l + ) * t + (ld)(l + r) * (ld)(r - l + ) / 2.0;
tree[o].sumxx = calc(s + r) - calc(s + l - );
tree[o].sumxy = (ld)(r - l + ) * s * t + ((ld)(l + r) * (ld)(r - l + ) / 2.0) * (ld)(s + t) + calc(r) - calc(l - );
can1[o] = ;
can2[o] = ;
return;
}
pushdown(o, l, r);
int mid = (l + r) >> ;
update3(l, mid, o << , a, b, s, t);
update3(mid + , r, o << | , a, b, s, t);
tree[o] = merge(tree[o << ], tree[o << | ]);
}
} t;
int main()
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i)
scanf("%lf", &x[i]);
for(int i = ; i <= n; ++i)
scanf("%lf", &y[i]);
t.build(, n, );
for(int i = ; i <= m; ++i)
{
int opt, l, r;
ld S, T;
scanf("%d", &opt);
if(opt == )
{
scanf("%d%d", &l, &r);
node o = t.query(, n, , l, r);
ld ox = o.sumx / (ld)(r - l + ), oy = o.sumy / (ld)(r - l + );
ld up = ((ld)(r - l + ) * o.sumxy - o.sumx * o.sumy), down = ((ld)(r - l + ) * o.sumxx - o.sumx * o.sumx), ans = up / down;
printf("%.10f\n", ans);
}
if(opt == )
{
scanf("%d%d%lf%lf", &l, &r, &S, &T);
t.update2(, n, , l, r, S, T);
}
if(opt == )
{
scanf("%d%d%lf%lf", &l, &r, &S, &T);
t.update3(, n, , l, r, S, T);
}
}
return ;
}

bzoj4821的更多相关文章

  1. 【BZOJ4821】[SDOI2017]相关分析(线段树)

    [BZOJ4821][SDOI2017]相关分析(线段树) 题面 BZOJ 洛谷 题解 看看询问要求的东西是什么.把所有的括号拆开,不难发现要求的就是\(\sum x,\sum y,\sum xy,\ ...

  2. BZOJ4821 SDOI2017相关分析(线段树)

    纯粹的码农题.维护x的和.y的和.xy的和.x2的和即可.可能会炸long long. #include<iostream> #include<cstdio> #include ...

  3. 【BZOJ4821】[Sdoi2017]相关分析 线段树

    [BZOJ4821][Sdoi2017]相关分析 Description Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. ...

  4. [bzoj4821][Sdoi2017]相关分析

    来自FallDream的博客,未经允许,请勿转载,谢谢. Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等.Frank不仅喜 ...

  5. 【BZOJ4821】【SDOI2017】相关分析 [线段树]

    相关分析 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Frank对天文学非常感兴趣,他经 ...

  6. bzoj4821 && luogu3707 SDOI2017相关分析(线段树,数学)

    题目大意 给定n个元素的数列,每一个元素有x和y两种元素,现在有三种操作: \(1\ L\ R\) 设\(xx\)为\([l,r]\)的元素的\(x_i\)的平均值,\(yy\)同理 求 \(\fra ...

  7. SDOI2017第一轮

    本蒟蒻表示终于$AC$了$SDOI2017\text{第一轮}$! 兴奋! 附上各个题的题解: $DAT1$: $T1$: BZOJ4816: [Sdoi2017]数字表格 $T2$: BZOJ481 ...

  8. SDOI2017 Round1 Day2 题解

    T2好厉害啊……AK不了啦……不过要是SCOI考这套题就好了240保底. BZOJ4819 新生舞会 模板题,分数规划+二分图最大权匹配. 费用流跑得过,可以不用KM. UPD:分数规划用迭代跑得飞快 ...

随机推荐

  1. ubuntu 16.04 添加网卡

    root@ubuntu:~# ls /sys/class/net/ enp0s3 enp0s8 lo root@ubuntu:~# vim /etc/network/interfaces # This ...

  2. 牛客多校Round 3

    Solved:2 rank:306 跑路场..... A.PACM team 简单背包记录路径都写挂 退役算了 #include <bits/stdc++.h> using namespa ...

  3. 自定义php函数的mysql数据库pdo包装

    define('DB_DSN','mysql:dbname=数据库名;charset=UTF8');define('DB_USER','root');define('DB_PASSWORD',''); ...

  4. <SpringMvc>入门四 响应结果

    1.响应String类型 根据试图解析器,去找相对应的jsp Model将对象存在request中 2.响应void类型 可以看出,此时void方法执行了,系统默认会去找testVoid.jsp 意思 ...

  5. Go:值类型、引用类型

    值类型,变量存的就是值本身: in系列t.float系列.bool.string.数组和struct 引用类型,变量存的是一个地址,这是地址存的才是值本身: 指针.slice.map.chan.int ...

  6. [luoguP1280] 尼克的任务(DP)

    传送门 原本想着 f[i] 表示前 i 个任务的最优答案,但是不好转移 看了题解后,发现是 f[i] 表示前 i 分钟的最优解,看来还是不能死脑筋,思维得活跃,一个思路行不通就换一个思路. 把 f 数 ...

  7. 【Java基础】基本类型与运算【重要】

    0.   Java基本数据类型 Java的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long.int.short.char和 byte,位运算符具体如下表 ...

  8. 洛谷(cogs 1293/bzoj 1212) P2292 [HNOI2004]L语言

    1293. [HNOI2004] L语言 ★★★   输入文件:language.in   输出文件:language.out   简单对比时间限制:1 s   内存限制:162 MB [题目描述] ...

  9. Linux运行级别研究(转)

    Linux系统中的运行级别 7种运行级别 运行级别(Runlevel)指的是Unix或者Linux等类Unix操作系统的运行模式,不同的运行模式下系统的功能也有所有不同.Linux 系统下通常分为7种 ...

  10. Spark之安装和使用

    Scala安装 Spark使用Scala开发,安装的Scala版本必须和Spark使用的版本一致,否则使用Scala编写的Spark任务会有兼容性问题 可以到Spark官网查看确定Scala版本,或者 ...