「SDOI2017」相关分析

题目链接https://loj.ac/problem/2005


题解

把上面的式子拆掉,把下面的式子拆掉。

发现所有的东西都能用线段树暴力维护。

代码

#include <bits/stdc++.h>

#define N 100010 

#define ls p << 1

#define rs p << 1 | 1

using namespace std;

typedef double db;

typedef double ll;

ll sum[N << 2], tagx1[N << 2], tagx2[N << 2], tagy1[N << 2], tagy2[N << 2], sum2[N << 2];

bool tag1[N << 2], tag2[N << 2];

ll sumx[N << 2], sumy[N << 2];

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
} inline void pushup(int p) {
sum[p] = sum[ls] + sum[rs];
sumx[p] = sumx[ls] + sumx[rs];
sumy[p] = sumy[ls] + sumy[rs];
sum2[p] = sum2[ls] + sum2[rs];
} void pls1(int l, int r, int s, int t, int p) {
int L = r - l + 1;
sum[p] += (ll)t * sumx[p] + (ll)s * sumy[p] + (ll)s * t * L;
sum2[p] += sumx[p] * s * 2 + (ll)s * s * L;
sumx[p] += (ll)s * L;
sumy[p] += (ll)t * L;
if (tag2[p]) {
tagx2[p] += s;
tagy2[p] += t;
}
else {
tagx1[p] += s;
tagy1[p] += t;
tag1[p] = true;
}
} inline ll bfr2(int x) {
return (ll)x * (x + 1) * (2 * x + 1) / 6;
} inline ll bfr1(int x) {
return (ll)x * (x + 1) / 2;
} void pls2(int l, int r, int s, int t, int p) {
int L = r - l + 1;
sum[p] = bfr2(r) - bfr2(l - 1) + (ll)(s + t) * (bfr1(r) - bfr1(l - 1)) + (ll)L * s * t;
sum2[p] = bfr2(r) - bfr2(l - 1) + (ll)2 * s * (bfr1(r) - bfr1(l - 1)) + (ll)L * s * s;
sumx[p] = bfr1(r) - bfr1(l - 1) + (ll)L * s;
sumy[p] = bfr1(r) - bfr1(l - 1) + (ll)L * t;
tag1[p] = false;
tagx1[p] = tagy1[p] = 0;
tag2[p] = true;
tagx2[p] = s;
tagy2[p] = t;
} inline void pushdown(int l, int r, int p) {
if (tag1[p]) {
int mid = (l + r) >> 1;
pls1(l, mid, tagx1[p], tagy1[p], ls);
pls1(mid + 1, r, tagx1[p], tagy1[p], rs);
tagx1[p] = tagy1[p] = 0;
tag1[p] = false;
}
if (tag2[p]) {
int mid = (l + r) >> 1;
pls2(l, mid, tagx2[p], tagy2[p], ls);
pls2(mid + 1, r, tagx2[p], tagy2[p], rs);
tagx2[p] = tagy2[p] = 0;
tag2[p] = false;
}
} void update1(int x, int y, int s, int t, int l, int r, int p) {
if (x <= l && r <= y) {
pls1(l, r, s, t, p);
return;
}
int mid = (l + r) >> 1;
pushdown(l, r, p);
if (x <= mid) {
update1(x, y, s, t, l, mid, ls);
}
if (mid < y) {
update1(x, y, s, t, mid + 1, r, rs);
}
pushup(p);
} void update2(int x, int y, int s, int t, int l, int r, int p) {
if (x <= l && r <= y) {
pls2(l, r, s, t, p);
return;
}
int mid = (l + r) >> 1;
pushdown(l, r, p);
if (x <= mid) {
update2(x, y, s, t, l, mid, ls);
}
if (mid < y) {
update2(x, y, s, t, mid + 1, r, rs);
}
pushup(p);
} ll queryx1(int x, int y, int l, int r, int p) {
if (x <= l && r <= y) {
return sumx[p];
}
int mid = (l + r) >> 1;
ll ans = 0;
pushdown(l, r, p);
if (x <= mid) {
ans += queryx1(x, y, l, mid, ls);
}
if (mid < y) {
ans += queryx1(x, y, mid + 1, r, rs);
}
return ans;
} ll queryy1(int x, int y, int l, int r, int p) {
if (x <= l && r <= y) {
return sumy[p];
}
int mid = (l + r) >> 1;
ll ans = 0;
pushdown(l, r, p);
if (x <= mid) {
ans += queryy1(x, y, l, mid, ls);
}
if (mid < y) {
ans += queryy1(x, y, mid + 1, r, rs);
}
return ans;
} ll query(int x, int y, int l, int r, int p) {
if (x <= l && r <= y) {
return sum[p];
}
int mid = (l + r) >> 1;
ll ans = 0;
pushdown(l, r, p);
if (x <= mid) {
ans += query(x, y, l, mid, ls);
}
if (mid < y) {
ans += query(x, y, mid + 1, r, rs);
}
return ans;
} ll query2(int x, int y, int l, int r, int p) {
if (x <= l && r <= y) {
return sum2[p];
}
int mid = (l + r) >> 1;
ll ans = 0;
pushdown(l, r, p);
if (x <= mid) {
ans += query2(x, y, l, mid, ls);
}
if (mid < y) {
ans += query2(x, y, mid + 1, r, rs);
}
return ans;
} ll a1[N], a2[N]; void build(int l, int r, int p) {
if (l == r) {
sum[p] = a1[l] * a2[l];
sum2[p] = a1[l] * a1[l];
sumx[p] = a1[l];
sumy[p] = a2[l];
return;
}
int mid = (l + r) >> 1;
build(l, mid, ls);
build(mid + 1, r, rs);
pushup(p);
} int main() {
// freopen("gold.in", "r", stdin);
// freopen("gold.out", "w", stdout);
int n = rd(), Q = rd();
for (int i = 1; i <= n; i ++ ) {
a1[i] = rd();
}
for (int i = 1; i <= n; i ++ ) {
a2[i] = rd();
}
build(1, n, 1);
while (Q -- ) {
int opt = rd();
if (opt == 1) {
int l = rd(), r = rd();
db Up;
int L = r - l + 1;
Up = query(l, r, 1, n, 1);
Up -= (db)queryx1(l, r, 1, n, 1) * queryy1(l, r, 1, n, 1) / L;
db Down;
Down = query2(l, r, 1, n, 1);
Down -= (db)queryx1(l, r, 1, n, 1) * queryx1(l, r, 1, n, 1) / L;
printf("%.10lf\n", Up / Down);
}
else if (opt == 2) {
int l = rd(), r = rd(), s = rd(), t = rd();
update1(l, r, s, t, 1, n, 1);
}
else {
int l = rd(), r = rd(), s = rd(), t = rd();
update2(l, r, s, t, 1, n, 1);
}
}
return 0;
}

小结:对拍的时候要记得,数据尽量和题面吻合,不然容易出一些奇奇怪怪的错误。比如说这个题考试的时候,我就有个值忘记开$long\ long$,对拍没拍出来因为我保证数据非常小。

[loj#2005][SDOI2017]相关分析 _线段树的更多相关文章

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

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

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

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

  3. 洛谷3707 [SDOI2017] 相关分析 【线段树】

    分析: 化简一下就行了,注意一下平方和公式的运用以及精度的误差. 代码: #include<bits/stdc++.h> using namespace std; ; int n,m; i ...

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

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

  5. BZOJ_4636_蒟蒻的数列_线段树+动态开点

    BZOJ_4636_蒟蒻的数列_线段树+动态开点 Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将 ...

  6. BZOJ_3252_攻略_线段树+dfs序

    BZOJ_3252_攻略_线段树+dfs序 Description 题目简述:树版[k取方格数] 众所周知,桂木桂马是攻略之神,开启攻略之神模式后,他可以同时攻略k部游戏.今天他得到了一款新游戏< ...

  7. BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针

    BZOJ_4653_[Noi2016]区间_线段树+离散化+双指针 Description 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间, ...

  8. BZOJ_2124_等差子序列_线段树+Hash

    BZOJ_2124_等差子序列_线段树+Hash Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pL ...

  9. BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...

随机推荐

  1. LA 6972 Domination

    6972 Domination Edward is the headmaster of Marjar University. He is enthusiastic about chess and of ...

  2. assert 笔记

    目录 什么是assert? assert使用 assert错误使用 什么是assert? Python 的 assert 语句是一个 debug 的好工具,主要用于测试一个条件是否满足.如果测试的条件 ...

  3. Codeforces 940 E.Cashback (单调队列,dp)

    Codeforces 940 E.Cashback 题意:一组数,要分为若干个区间,每个区间长度为ki(1<=ki<=n),并且对于每个区间删去前ki/c(向下取整)个小的数(即对区间升序 ...

  4. 使用UltraISO制作linux系统安装u盘启动盘

    1.首先打开UltraISO软件,尽量下载最新版的,小编曾用某个旧版的UltraISO,制作的安装盘,不能不能识别磁盘,安装失败! 2.点击工具栏中的第二个打开镜像文件工具,如图红色方框标志按钮,然后 ...

  5. 前端知识点回顾——Javascript篇(四)

    Symbol 为什么需要symbol ES5里面对象的属性名都是字符串,如果你需要使用一个别人提供的对象,你对这个对象有哪些属性也不是很清楚,但又想为这个对象新增一些属性,那么你新增的属性名就很可能和 ...

  6. C memcpy()用法

    https://blog.csdn.net/qq_21792169/article/details/50561570

  7. 2.3 Go语言基础之数组

    本文主要介绍Go语言中数组(array)及它的基本使用. 一.Array(数组) 数组是同一种数据类型元素的集合. 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化. 基 ...

  8. Android关闭通知栏后toast无法提示的解决方案

    https://github.com/getActivity/ToastUtils PS:release版本注意加上混淆规则

  9. JS选择器querySelector和~All,三个原生选择器

    定义: querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素. 注意: querySelector() 方法仅仅返回匹配指定选择器的第一个元素.如果你需要返回所有的元素,请 ...

  10. Java SpringBoot React Redux

    1.字符串转换相关 - React 前端JS部分 JSON.parse(JSON.stringify(copyRow)); 2.字符串分隔相关,弹出confirm确认框,显示换行信息 - React ...