bzoj4821
线段树
这题真是无聊
把式子拆开,然后可知维护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的更多相关文章
- 【BZOJ4821】[SDOI2017]相关分析(线段树)
[BZOJ4821][SDOI2017]相关分析(线段树) 题面 BZOJ 洛谷 题解 看看询问要求的东西是什么.把所有的括号拆开,不难发现要求的就是\(\sum x,\sum y,\sum xy,\ ...
- BZOJ4821 SDOI2017相关分析(线段树)
纯粹的码农题.维护x的和.y的和.xy的和.x2的和即可.可能会炸long long. #include<iostream> #include<cstdio> #include ...
- 【BZOJ4821】[Sdoi2017]相关分析 线段树
[BZOJ4821][Sdoi2017]相关分析 Description Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等. ...
- [bzoj4821][Sdoi2017]相关分析
来自FallDream的博客,未经允许,请勿转载,谢谢. Frank对天文学非常感兴趣,他经常用望远镜看星星,同时记录下它们的信息,比如亮度.颜色等等,进而估算出星星的距离,半径等等.Frank不仅喜 ...
- 【BZOJ4821】【SDOI2017】相关分析 [线段树]
相关分析 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Frank对天文学非常感兴趣,他经 ...
- bzoj4821 && luogu3707 SDOI2017相关分析(线段树,数学)
题目大意 给定n个元素的数列,每一个元素有x和y两种元素,现在有三种操作: \(1\ L\ R\) 设\(xx\)为\([l,r]\)的元素的\(x_i\)的平均值,\(yy\)同理 求 \(\fra ...
- SDOI2017第一轮
本蒟蒻表示终于$AC$了$SDOI2017\text{第一轮}$! 兴奋! 附上各个题的题解: $DAT1$: $T1$: BZOJ4816: [Sdoi2017]数字表格 $T2$: BZOJ481 ...
- SDOI2017 Round1 Day2 题解
T2好厉害啊……AK不了啦……不过要是SCOI考这套题就好了240保底. BZOJ4819 新生舞会 模板题,分数规划+二分图最大权匹配. 费用流跑得过,可以不用KM. UPD:分数规划用迭代跑得飞快 ...
随机推荐
- Linux System
Linux System linux 是一个功能强大的操作系统,同时它是一个自由软件,是免费的.源代码开放的,编制它的目的是建立不受任何商品化软件版权制约的.全世界都能自由使用的UNIX兼容产品.各种 ...
- js识别手机访问自动跳转到相应页面
/* * 智能机浏览器版本信息: * */ var browser={ versions:function(){ var u = navigator.userAgent, app = navigato ...
- 字符串系列——KMP模板整理
KMP模板整理 KMP与扩展KMP: /*vs 2017/ vs code以外编译器,去掉windows.h头文件和system("pause");*/ #include<i ...
- 洛谷——P3946 ことりのおやつ(小鸟的点心)
P3946 ことりのおやつ(小鸟的点心) 题目太长,请去链接里看吧 注意细节:特判终点(即使困住又能怎样,到达就好了),特判高度 #include<bits/stdc++.h> #defi ...
- linux more-显示文件内容,每次显示一屏
博主推荐:获取更多 linux文件内容查看命令 收藏:linux命令大全 more命令是一个基于vi编辑器文本过滤器,它以全屏幕的方式按页显示文本文件的内容,支持vi中的关键字定位操作.more名单中 ...
- LINUX-字符设置和文件格式转换
dos2unix filedos.txt fileunix.txt 将一个文本文件的格式从MSDOS转换成UNIX unix2dos fileunix.txt filedos.txt 将一个文本文件的 ...
- Python selenium chrome打包exe后禁用控制台输出滚动日志
Python selenium chrome打包exe后,在运行的过程中,如果遇到需要input()输入时,会发现被不断滚动刷新的日志把命令行输入快速顶掉了,通过查阅资料不断实践,发现以下方法有效: ...
- getContextPath和getRealPath的区别-----其实主要区别就是相对路径和绝对路径
getContextPath和getRealPath的区别 其实主要区别就是相对路径和绝对路径 https://blog.csdn.net/zsmj_2011/article/details/4121 ...
- 九度oj 题目1078:二叉树遍历
题目1078:二叉树遍历 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5326 解决:3174 题目描述: 二叉树的前序.中序.后序遍历的定义: 前序遍历:对任一子树,先访问跟,然后遍历 ...
- 用Windows自带DOS命令提示符 制作U盘启动盘
Windows & DOS命令提示符 & U盘 & 启动盘 用Windows自带DOS命令提示符 制作U盘启动盘.docx http://xgqfrms.blog.163.co ...