第一次写泰勒展开;本地和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的更多相关文章

  1. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  2. Codechef September Challenge 2018 游记

    Codechef September Challenge 2018 游记 Magician versus Chef 题目大意: 有一排\(n(n\le10^5)\)个格子,一开始硬币在第\(x\)个格 ...

  3. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  4. Codechef October Challenge 2018 游记

    Codechef October Challenge 2018 游记 CHSERVE - Chef and Serves 题目大意: 乒乓球比赛中,双方每累计得两分就会交换一次发球权. 不过,大厨和小 ...

  5. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

  6. Codechef August Challenge 2018 : Coordinate Compression

    传送门 外边二分,里面拿线段树维护贪心就行了. #include<cstdio> #include<vector> #include<cstring> #inclu ...

  7. Codechef August Challenge 2019 Chef and Gordon Ramsay

    [传送门] 题目即求所有的三元组,相对大小关系同 $p_1,p_2,p_3$. 题解说都很清楚,这里写一下过程整理一下思路. 如果我们枚举中间这个元素,那么就是统计子树内外有多少个大于这个数和小于这个 ...

  8. 2019.02.14 codechef Chef at the Food Fair(线段树+泰勒展开)

    传送门 题意:现在有nnn个位置,每个位置上有一个值aia_iai​. 要求支持如下两种操作: 区间乘vvv 求区间的(1−ai)(1-a_i)(1−ai​)之积 思路: 考虑转换式子: Ans=∏i ...

  9. 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu

    https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...

随机推荐

  1. web项目部署后动态编译无法找到依赖的jar包

    很纳闷的一个问题,通过配置文件生成的java源码在本地动态编译没有问题,但是部署服务器后编译不通过,找不到依赖的jar包. 通过网上查资料,找到一个兄弟提供的方法,问题解决了:下面贴出代码以供参考: ...

  2. QCTF 2018线上赛 writeup

    本次算是被QCTF打趴了,本来做题时间就少(公司无限开会,开了一天,伪借口),加上难度和脑洞的增大,导致这次QCTF又酱油了...就连最基本的签到题都没做出来...这就很气 好了,以下是解题思路 MI ...

  3. docker镜像删除

    1. 查看镜像 docker images [-q] 只列出image id [-a] 列出所有的image 2. 查看运行的镜像 docker ps [-q] 只列出container id [-a ...

  4. python所有的魔术方法

    据说,Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切. 他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个, ...

  5. POJ1741(点分治)

    分治的时候SZ感觉是错的--但是貌似第一次找好重心就够了,之后SZ别太离谱就不会T,重心随一随缘就好-- #include <cstdio> #include <cstring> ...

  6. QDU第一届程序设计大赛——E到I题解法(非官方题解)

    题目链接https://qduoj.com/contest/28/problems,密码:qdu1230 E题: 思路:先进行排序,然后去暴力模拟就可以,但可能WA了几次,导致此题没解出来,有点可惜 ...

  7. 前端CSS(3)

    前端基础CSS(3)   一.文本属性和字体属性(常用的) 1.文本属性 text-align:left|right|center|justify(两端对齐,只适用于英文);   /*对齐方式*/ c ...

  8. Rebus消息总线

    这里主要讲一下我基于Rebus写的一个ABP框架的模块   目录结构 对于Rebus网上的资料很少,其实我对于服务总线也不是很理解 ..个人理解的就是像ABP中的EventBus那样的,但是集成了一些 ...

  9. 引擎基本服务接口API介绍

    Slickflow.NET 开源工作流引擎基础介绍(一) -- 引擎基本服务接口API介绍 https://www.cnblogs.com/slickflow/p/4807227.html 工作流术语 ...

  10. openstack修改增加网卡及更改ip

        1.neutron更改及mysql数据库更改网卡及ip:     neutron port-update ae22c84b-22a9-4618-b046-1eb61379bcea  --all ...