线段树

这题真是无聊

把式子拆开,然后可知维护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. Calendar的用法

    DAY_OF_MONTH的主要作用是cal.get(DAY_OF_MONTH),用来获得这一天在是这个月的第多少天 Calendar.DAY_OF_YEAR的主要作用是cal.get(DAY_OF_Y ...

  2. 08css、JS

    08.css.JS-2018/07/18 1.css的属性 文字属性:font-size:大小,font-family字体类型,font-color:颜色 文本颜色:color:颜色,test-dec ...

  3. 配置Struts2后运行jsp出现404的解决方法

    更新:善用控制台查看错误信息 --------------------------------------------- 原因:Java Build Path没有导入正确的jar包或者导入了但没有把相 ...

  4. SQL学习笔记:基础SQL语句

    目录 语句特点 进入数据库 基本查询语句 SELECT DISTINCT WHERE AND/OR/NOT :逻辑运算符 ORDER BY :排序 基本修改语句 INSERT:添加语句 UPDATE: ...

  5. Android StatusBarUtil:设置Android系统下方虚拟键键盘透明度

     Android StatusBarUtil:设置Android系统下方虚拟键键盘透明度 Android StatusBarUtil是github上的一个开源项目,主页:https://githu ...

  6. [luoguP2659] 美丽的序列(单调栈)

    传送门 单调栈大水题 l[i] 表示 i 能扩展到的左边 r[i] 表示 i 能扩展到的右边 ——代码 #include <cstdio> #include <iostream> ...

  7. 选择数字(codevs 3327)

    题目描述 Description 给定一行n个非负整数a[1]..a[n].现在你可以选择其中若干个数,但不能有超过k个连续的数字被选择.你的任务是使得选出的数字的和最大. 输入描述 Input De ...

  8. 【BZOJ3676&UOJ103】回文串(manacher,Trie)

    题意:考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度. 请你求出s的所有回文子串中的最大出现值. len<=300000 思路:鸣谢UO ...

  9. [poj1678]I Love this Game!_博弈论

    I Love this Game! 题目大意:题目链接 注释:略. 想法: 开始的时候以为没法dp,结果...:a>0啊! 所以可以直接dp了啊! 状态:dp[i]表示先手选了a[i]的状态. ...

  10. T1080 线段树练习 codevs

    http://codevs.cn/problem/1080/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 一行N个方 ...