题面

传送门

分析

计算的部分其他博客已经写的很清楚了,本博客主要提供一个简洁的实现方法

尤其是pushdown函数写得很简洁

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,m;
double x[maxn];
double y[maxn]; double get_sumx(double l,double r) {//返回l+(l+1)+...+r
return (l+r)*(r-l+1)/2;
} double get_sumsqx(double l,double r) {//返回l^2+(l+1)^2+...+r^2
return r*(r+1)*(2*r+1)/6-(l-1)*l*(2*l-1)/6;
} struct segment_tree {
#define lson pos<<1//宏,简化代码
#define rson pos<<1|1
struct node {
int l;//记录区间端点,方便在计算中调用
int r;
double sx;
double sy;
double sqx;
double xy;
double addx;
double addy;
double len() {//返回区间长度,同样是方便计算
return r-l+1;
}
bool set;
} tree[maxn<<2]; void push_up(int pos) {
tree[pos].sx=tree[lson].sx+tree[rson].sx;
tree[pos].sy=tree[lson].sy+tree[rson].sy;
tree[pos].sqx=tree[lson].sqx+tree[rson].sqx;
tree[pos].xy=tree[lson].xy+tree[rson].xy;
} void push_down(int pos) {
int son=pos<<1;
if(tree[pos].set) {
for(int i=0; i<=1; i++) {//用循环来遍历,少写一次代码
son=son|i;
tree[son].addx=tree[son].addy=0;
tree[son].sx=tree[son].sy=get_sumx(tree[son].l,tree[son].r);
tree[son].xy=tree[son].sqx=get_sumsqx(tree[son].l,tree[son].r);
tree[son].set=1;
}
tree[pos].set=0;
}
if(tree[pos].addx||tree[pos].addy) {
son=pos<<1;
double mkx=tree[pos].addx;
double mky=tree[pos].addy;
for(int i=0; i<=1; i++) {
son=son|i;
tree[son].addx+=mkx;
tree[son].addy+=mky;
tree[son].sqx+=2*tree[son].sx*mkx+mkx*mkx*tree[son].len();
tree[son].xy+=tree[son].len()*mkx*mky+tree[son].sx*mky+tree[son].sy*mkx;
tree[son].sx+=mkx*tree[son].len();
tree[son].sy+=mky*tree[son].len();
}
tree[pos].addx=tree[pos].addy=0;
}
} void build(int l,int r,int pos,double *x,double *y) {
tree[pos].l=l;
tree[pos].r=r;
if(l==r) {
tree[pos].sx=x[l];
tree[pos].sy=y[l];
tree[pos].sqx=x[l]*x[l];
tree[pos].xy=x[l]*y[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,pos<<1,x,y);
build(mid+1,r,pos<<1|1,x,y);
push_up(pos);
} void add_segment(int L,int R,int pos,double s,double t) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
tree[pos].addx+=s;
tree[pos].addy+=t;
tree[pos].xy+=tree[pos].sx*t+tree[pos].sy*s+s*t*tree[pos].len();
tree[pos].sqx+=2*tree[pos].sx*s+s*s*tree[pos].len();
tree[pos].sx+=s*tree[pos].len();
tree[pos].sy+=t*tree[pos].len();
return;
}
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) add_segment(L,R,pos<<1,s,t);
if(R>mid) add_segment(L,R,pos<<1|1,s,t);
push_up(pos);
} void set_segment(int L,int R,int pos) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
tree[pos].set=1;
tree[pos].addx=tree[pos].addy=0;
tree[pos].sx=tree[pos].sy=get_sumx(tree[pos].l,tree[pos].r);
tree[pos].sqx=tree[pos].xy=get_sumsqx(tree[pos].l,tree[pos].r);
return;
}
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) set_segment(L,R,pos<<1);
if(R>mid) set_segment(L,R,pos<<1|1);
push_up(pos);
} double query_sx(int L,int R,int pos) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
return tree[pos].sx;
}
push_down(pos);
double ans=0;
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) ans+=query_sx(L,R,pos<<1);
if(R>mid) ans+=query_sx(L,R,pos<<1|1);
return ans;
} double query_sy(int L,int R,int pos) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
return tree[pos].sy;
}
push_down(pos);
double ans=0;
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) ans+=query_sy(L,R,pos<<1);
if(R>mid) ans+=query_sy(L,R,pos<<1|1);
return ans;
} double query_sqx(int L,int R,int pos) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
return tree[pos].sqx;
}
push_down(pos);
double ans=0;
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) ans+=query_sqx(L,R,pos<<1);
if(R>mid) ans+=query_sqx(L,R,pos<<1|1);
return ans;
} double query_xy(int L,int R,int pos) {
if(L<=tree[pos].l&&R>=tree[pos].r) {
return tree[pos].xy;
}
push_down(pos);
double ans=0;
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) ans+=query_xy(L,R,pos<<1);
if(R>mid) ans+=query_xy(L,R,pos<<1|1);
return ans;
} #undef lson
#undef rson
} T; void debug(){
printf("debug:\n");
for(int i=1;i<=n;i++){
printf("%.0f ",T.query_sx(i,i,1));
}
printf("\n");
for(int i=1;i<=n;i++){
printf("%.0f ",T.query_sy(i,i,1));
}
printf("\n");
printf("\n");
}
int main() {
int cmd,l,r;
double s,t;
double up,down,ax,ay;
double sumx,sumy,sumxy,sumsqx;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%lf",&x[i]);
}
for(int i=1; i<=n; i++) {
scanf("%lf",&y[i]);
}
T.build(1,n,1,x,y);
for(int i=1; i<=m; i++) {
scanf("%d",&cmd);
if(cmd==2) {
scanf("%d %d %lf %lf",&l,&r,&s,&t);
T.add_segment(l,r,1,s,t);
} else if(cmd==3) {
scanf("%d %d %lf %lf",&l,&r,&s,&t);
T.set_segment(l,r,1);
T.add_segment(l,r,1,s,t);
} else {
scanf("%d %d",&l,&r);
sumx=T.query_sx(l,r,1);
sumy=T.query_sy(l,r,1);
sumxy=T.query_xy(l,r,1);
sumsqx=T.query_sqx(l,r,1);
// printf("x=%.0f y=%.0f xy=%.0f x^2=%.0f\n",sumx,sumy,sumxy,sumsqx);
ax=sumx/(r-l+1);
ay=sumy/(r-l+1);
up=ax*ay*(r-l+1)+sumxy-ay*sumx-ax*sumy;
down=sumsqx-2*ax*sumx+(r-l+1)*ax*ax;
printf("%.10f\n",up/down);
}
// debug();
}
}

BZOJ 4821 (luogu 3707)(全网最简洁的代码实现之一)的更多相关文章

  1. [Luogu 3707] SDOI2017 相关分析

    [Luogu 3707] SDOI2017 相关分析 前言 Capella 和 Frank 一样爱好天文学. 她常在冬季的夜晚,若有所思地望着东北方上空的五边形中,最为耀眼的一个顶点. 那一抹金黄曾带 ...

  2. BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)

    题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...

  3. BZOJ 3931 / Luogu P3171 [CQOI2015]网络吞吐量 (最大流板题)

    题面 中文题目,不解释: BZOJ传送门 Luogu传送门 分析 这题建图是显然的,拆点后iii和i′i'i′连容量为吞吐量的边,根据题目要求,111和nnn的吞吐量看作∞\infty∞. 然后用di ...

  4. BZOJ 3894 / Luogu P4313 文理分科 (拆点最小割)

    题面 中文题面- BZOJ 传送门 Luogu 传送门 分析 这道题类似于BZOJ 3774 最优选择,然后这里有一篇博客写的很好- Today_Blue_Rainbow's Blog 应该看懂了吧- ...

  5. BZOJ 2039 / Luogu P1791 [2009国家集训队]employ人员雇佣 (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 考虑如何最小割建图,因为这仍然是二元关系,我们可以通过解方程来确定怎么建图,具体参考论文 <<浅析一类最小割问题 湖南师大附中 彭天翼> ...

  6. BZOJ 2127 / Luogu P1646 [国家集训队]happiness (最小割)

    题面 BZOJ传送门 Luogu传送门 分析 这道题又出现了二元关系,于是我们只需要解方程确定怎么连边就行了 假设跟SSS分在一块是选文科,跟TTT分在一块是选理科,先加上所有的收益,再来考虑如何让需 ...

  7. (WA)BZOJ 4821: [Sdoi2017]相关分析

    二次联通门 : BZOJ 4821: [Sdoi2017]相关分析 2017.8.23 Updata 妈妈!!这道题卡我!!!就是不然我过!!!!! #include <cstdio> # ...

  8. [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表)

    [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表) 题面 Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段 ...

  9. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

随机推荐

  1. Git同步问题

    1. 无法合并不相关历史记录 git pull origin master --allow-unrelated-histories

  2. 四轴飞行器飞行原理与双闭环PID控制

    四轴轴飞行器是微型飞行器的其中一种,相对于固定翼飞行器,它的方向控制灵活.抗干扰能力强.飞行稳定,能够携带一定的负载和有悬停功能,因此能够很好地进行空中拍摄.监视.侦查等功能,在军事和民用上具备广泛的 ...

  3. LinuxC语言实现ATM取款机实验Socket

    链接:https://pan.baidu.com/s/1sZt4qhYc6CDJVpoJHbtw-Q 提取码:53ot 复制这段内容后打开百度网盘手机App,操作更方便哦 本实验用的是Centos7t ...

  4. MYSQL学习笔记——数据类型

    mysql的数据类型可以分为三大类,分别是数值数据类型.字符串数据类型以及日期时间数据类型. 数值数据类型                                               ...

  5. touch 创建空文件或改变文件的时间戳属性

    1.命令功能 touch 改变文件时间属性或创建空文件. 2.语法格式 touch  [option]  file touch 选项 文件名 3. 选项参数说明 参数 参数说明 -a 仅改变文件的访问 ...

  6. 1142. Maximal Clique (25)

    A clique is a subset of vertices of an undirected graph such that every two distinct vertices in the ...

  7. 2 什么是编码?什么是Unicode?

    为了避免在浏览器中传输数据的时候出现中文乱码,我们可以将内容进行URL编码,当然也可以将内容进行UNICODE编码.将汉字进行UNICODE编码,如:“王”编码后就成了“\u738b”,UNICODE ...

  8. linux运维、架构之路-网络基础

    一. 常用网络设备 1.交换机:实现多台主机之间互相通讯的需求 交换机实现互相通讯的要求: ①主机身份标识信息:mac地址,利用源mac和目标mac地址,进行身份信息识别 ②主机通过交换机识别目标主机 ...

  9. 16 :IDEA快速键

    ctrol+z ctrol+shift+z  重做 复制,粘贴,删除,(行操作,光标放在那里就可以操作,不要全选择) 注:特别:查询出来,文件是可以直接编辑的 crtol+F double +shif ...

  10. spring boot整合WebSocket示例

    1.运行环境 开发工具:intellij idea JDK版本:1.8 项目管理工具:Maven 4.0.0 2.GITHUB地址 https://github.com/nbfujx/springBo ...