第一次写泰勒展开;本地和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. 3、CreateJS介绍-SoundJS

    需要在html5文件中引入的CreateJS库文件是soundjs-0.5.2.min.js HTML5文件如下: <!DOCTYPE html> <html lang=" ...

  2. C# File和fileinfo类

    两个类功能差不多,File是静态方法实现的,Fileinfo通过实例方法实现的: 文件操作例子: using System; using System.Collections.Generic; usi ...

  3. 长春理工大学第十四届程序设计竞赛(重现赛)I.Fate Grand Order

    链接:https://ac.nowcoder.com/acm/contest/912/I 题意: Fate Grand Order是型月社发行的角色扮演类手机游戏,是著名的氪金抽卡"垃圾&q ...

  4. Codeforces Round #562 (Div. 2) A.Circle Metro

    链接:https://codeforces.com/contest/1169/problem/A 题意: The circle line of the Roflanpolis subway has n ...

  5. CodeForces - 1004A-Sonya and Hotels(思维)

    Sonya decided that having her own hotel business is the best way of earning money because she can pr ...

  6. CSS3动画总结学习(一)

    参考文章: CSS3 Transitions, Transforms和Animation使用简介与应用展示 CSS 参考手册 动画的分类 平移动画 transform: 就是变换, 变换, 变换 也就 ...

  7. JAVA_HOME not recognized by tomcat7 in Ubuntu

    vi .bashrc 添加: export JAVA_HOME=/usr/lib/jvm/java--oracle export JRE_HOME=$JAVA_HOME/jre export CLAS ...

  8. 小G搭积木

    A小 G 搭积木文件名 输入文件 输出文件 时间限制 空间限制box.cpp box.in box.out 2s 128MB题目描述小 G 喜欢搭积木.小 G 一共有 n 块积木,并且积木只能竖着一块 ...

  9. Spring连接数据库

    public class Book { private int bookid; private String bookname; private String bookauthor; private ...

  10. swift 第三方库迁移错误解决“Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choo

    先看看错误提示 这里Alamofire库报错,原因打开工程会Xcode会提示你覆盖到最新的3.0版本.但是仍然有些框架会出现一些问题 解决办法: 选择Pods - ReactiveCocoa - Sw ...