【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair
第一次写泰勒展开;本地和CC差距好大
题目大意
大厨住的城市里办了一场美食节。一条街上开设了$N$个摊位,编号为$1∼N$。这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$。在这一天中,大厨发现某些摊位可能会根据顾客的反馈提供没那么有毒的食物。你需要处理$Q$个询问,询问有以下两类:
0 L R:求出:如果要吃遍$[L,R]$内所有摊位的食物,那么不会食物中毒的概率是多少;
1 L R T:$[L,R]$中的所有摊位的食物会导致食物中毒的概率变为了原来的$T$倍。$T$是一个小于$1$的非负实数。
对于前 $20\%$ 的数据,$n,m\le 2000$
另有 $20\%$ 的数据,$T\le 0.5$
对于 $100\%$ 的数据,满足 $n,m\le 10^5,0\le T<1,P_i\le 1,1\le L\le R\le n$,保证输入数据不超过 $6$ 位小数。
题目分析
注意到维护的操作有些不同寻常。
- 第一:维护的是$\prod (1-P_i)$
- 第二:每次操作是区间乘法
对于要求支持区间乘的问题,有一种转化套路是将它取$\ln$,那么问题就变成了维护区间和。
那么这题中还需要处理$\ln (1-P_i)$,将它泰勒展开得到$\ln(1-x)=x-{1\over 2}x^2-{1\over 3}x^3-...-{1\over n}x^n+R(x)$。我们一如既往地爆精度,只需要保留这个式子的前$MAXD=100$项和。维护时则是开$MAXD$颗线段树对每类次项分别处理区间乘法。
需要注意的是,这题需要一些常数技巧。我最先是开了$f[MAXD]$颗封装好的线段树,但由于数组的第一维是更频繁访问的一维,所以实际运行效率会比较低。如果采用形如$f[maxn<<2][MAXD]$的做法,就会快非常多。
非常迷的一点是,同一份代码在本地考试的数据下,极限数据要跑个4~5s;但是交到CC上就rank2了……
#include<bits/stdc++.h>
const int maxn = ;
const double eps = 1e-; int n,m,MAXD;
double p[maxn],w[maxn],K,S;
double f[maxn<<][],tag[maxn<<]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void pushup(int rt)
{
for (int i=; i<=MAXD; i++)
f[rt][i] = f[rt<<][i]+f[rt<<|][i];
}
void pushdown(int rt)
{
double v = tag[rt], s = tag[rt];
if (fabs(1.0-v) > eps){
tag[rt<<] *= v, tag[rt<<|] *= v;
for (int i=; i<=MAXD; i++)
f[rt<<][i] *= s, f[rt<<|][i] *= s, s *= v;
tag[rt] = 1.0;
}
}
void build(int rt, int l, int r)
{
tag[rt] = 1.0;
if (l==r){
for (int i=; i<=MAXD; i++)
w[l] *= p[l], f[rt][i] = w[l]/i;
return;
}
int mid = (l+r)>>;
build(rt<<, l, mid);
build(rt<<|, mid+, r);
pushup(rt);
}
double query(int rt, int L, int R, int l, int r)
{
if (L <= l&&r <= R){
double ret = ;
for (int i=; i<=MAXD; i++)
ret += f[rt][i];
return ret;
}
int mid = (l+r)>>;
double ret = ;
pushdown(rt);
if (L <= mid) ret += query(rt<<, L, R, l, mid);
if (R > mid) ret += query(rt<<|, L, R, mid+, r);
return ret;
}
void modify(int rt, int L, int R, int l, int r, double c)
{
if (L <= l&&r <= R){
double s = c;
tag[rt] *= s;
for (int i=; i<=MAXD; i++)
f[rt][i] *= s, s *= c;
return;
}
int mid = (l+r)>>;
pushdown(rt);
if (L <= mid) modify(rt<<, L, R, l, mid, c);
if (R > mid) modify(rt<<|, L, R, mid+, r, c);
pushup(rt);
}
int main()
{
n = read(), m = read();
for (int i=; i<=n; i++) scanf("%lf",&p[i]), w[i] = 1.0;
MAXD = ;
build(, , n);
for (int i=; i<=m; i++)
{
int opt = read(), l = read(), r = read();
if (opt){
scanf("%lf",&K);
modify(, l, r, , n, K);
}else{
K = query(, l, r, , n);
printf("%.8lf\n",exp(-K));
}
}
return ;
}
END
【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair的更多相关文章
- Codechef August Challenge 2018 : Chef at the River
传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...
- Codechef September Challenge 2018 游记
Codechef September Challenge 2018 游记 Magician versus Chef 题目大意: 有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格 ...
- Codechef April Challenge 2019 游记
Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...
- Codechef October Challenge 2018 游记
Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...
- CodeChef April Challenge 2019题解
传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...
- Codechef August Challenge 2018 : Coordinate Compression
传送门 外边二分,里面拿线段树维护贪心就行了. #include<cstdio> #include<vector> #include<cstring> #inclu ...
- Codechef August Challenge 2019 Chef and Gordon Ramsay
[传送门] 题目即求所有的三元组,相对大小关系同 $p_1,p_2,p_3$. 题解说都很清楚,这里写一下过程整理一下思路. 如果我们枚举中间这个元素,那么就是统计子树内外有多少个大于这个数和小于这个 ...
- 2019.02.14 codechef Chef at the Food Fair(线段树+泰勒展开)
传送门 题意:现在有nnn个位置,每个位置上有一个值aia_iai. 要求支持如下两种操作: 区间乘vvv 求区间的(1−ai)(1-a_i)(1−ai)之积 思路: 考虑转换式子: Ans=∏i ...
- 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu
https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...
随机推荐
- Jeasyui的datagrid前端分页要点
Jeasyui的分页有两种方式: 1. 服务器端分页,是真正的分页,datagridview的pager会自动把pageSize和pageNum传到后台,后台根据根据pageSize和pageNum构 ...
- jar包冲突问题
这两天在启动一个新项目的时候,项目一直启动不了,报StackOverFlow; java.util.concurrent.ExecutionException: java.lang.StackOver ...
- Django (十三) 项目部署 3
阿里云项目部署 部署Django项目 1, 配置nginx 1.1 进入:cd /var/www, 将外面压缩好的AXF项目拖入xshell中,并解压 1.2 配置nginx.conf: 将htt ...
- NET高性能IO
System.IO.Pipelines: .NET高性能IO https://www.cnblogs.com/xxfy1/p/9290235.html System.IO.Pipelines是一个新的 ...
- setTimeout() 实现程序每隔一段时间自动执行
定义和用法 setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. 语法 setTimeout(code,millisec) 参数 描述 code 必需.要调用的函数后要执行的 Ja ...
- storm中的topology-worker-executor-task
调度角色 调度方法 自定义调度 1 调度角色 任务角色结构 上图是JStorm中一个topology对应的任务执行结构,其中worker是进程,executor对应于线程,task对应着spout ...
- C++程序中调用WebService的实现
前言 因为最近的项目中需要运用到在MFC程序中调用WebService里面集成好了的函数,所以特意花了一天的时间来研究WebService的构建以及如何在MFC的程序中添加Web引用,进而来实现在C+ ...
- Hybrid框架安全隐患分析
Hybrid框架安全隐患分析 目前我司移动端项目中各种app如雨后春笋般生根发芽层出不穷.而利用Hybrid框架确实可以减轻一部分移动端压力.并且做到灵活发版.但是其中的安全问题往往让人忽略. 针对A ...
- Android安卓电话拦截及短信过滤
package com.focus.manager; import java.lang.reflect.Method; import Android .app.Activity; import And ...
- 多段图动态规划dp
多段图问题是DP的基础题目.大体的意思是有一个赋权有向图,其顶点集被分为几个子集.求经过每个子集从源点到终点的最短路径 import java.util.ArrayList; import java. ...