传送门

题意:现在有nnn个位置,每个位置上有一个值aia_iai​.

要求支持如下两种操作:

  1. 区间乘vvv
  2. 求区间的(1−ai)(1-a_i)(1−ai​)之积

思路:

考虑转换式子:

Ans=∏i=lr(1−ai)=e∑i=lrln(1−ai)Ans=\prod_{i=l}^r(1-a_i)=e^{\sum_{i=l}^rln(1-a_i)}Ans=∏i=lr​(1−ai​)=e∑i=lr​ln(1−ai​)

于是只需维护∑i=lrln(1−ai)\sum_{i=l}^rln(1-a_i)∑i=lr​ln(1−ai​)

把这个式子在x0=0x_0=0x0​=0出泰勒展开可以得到:ln(1−x)=−x−12x2−13x3−⋯˙ln(1-x)=-x-\frac 12x^2-\frac 13x^3-\dot\cdotsln(1−x)=−x−21​x2−31​x3−⋯˙

因为允许一定的精度误差。

于是我们维护这个多项式的前若干项即可。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=1e5+5;
double a[N];
int n,m;
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (T[p].l+T[p].r>>1)
	struct Val{
		double a[100];
		inline double&operator[](const int&k){return a[k];}
		inline const double&operator[](const int&k)const{return a[k];}
	};
	struct Tag{double a;};
	const Tag tag_empty=(Tag){1};
	Val val_empty;
	inline Val operator+(const Val&a,const Val&b){
		Val ret;
		for(ri i=0;i<100;++i)ret[i]=a[i]+b[i];
		return ret;
	}
	inline void operator+=(Val&a,const Val&b){a=a+b;}
	inline Tag operator+(const Tag&a,const Tag&b){return (Tag){a.a*b.a};}
	inline void operator+=(Tag&a,const Tag&b){a=a+b;}
	inline Val operator+(const Val&a,const Tag&b){
		Val ret;
		double mult=b.a;
		for(ri i=0;i<100;++i)ret[i]=a[i]*mult,mult*=b.a;
		return ret;
	}
	inline void operator+=(Val&a,const Tag&b){a=a+b;}
	inline Val solve1(double a){
		Val ret=val_empty;
		double mult=a;
		for(ri i=0;i<100;++i)ret[i]=-mult/(i+1),mult*=a;
		return ret;
	}
	inline double solve2(Val a){
		double ret=0.0;
		for(ri i=0;i<100;++i)ret+=a[i];
		return ret;
	}
	struct Node{Val val;Tag tag;int l,r;}T[N<<2];
	inline void pushup(int p){T[p].val=T[lc].val+T[rc].val;}
	inline void pushnow(int p,Tag v){T[p].val+=v,T[p].tag+=v;}
	inline bool check(Tag a){return fabs(a.a-1)<=1e-9;}
	inline void pushdown(int p){
		if(check(T[p].tag))return;
		pushnow(lc,T[p].tag),pushnow(rc,T[p].tag);
		T[p].tag=tag_empty;
	}
	inline void build(int p,int l,int r){
		T[p]=(Node){val_empty,tag_empty,l,r};
		if(l==r){T[p].val=solve1(a[l]);return;}
		build(lc,l,mid),build(rc,mid+1,r),pushup(p);
	}
	inline void update(int p,int ql,int qr,Tag v){
		if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
		pushdown(p);
		if(ql<=mid)update(lc,ql,qr,v);
		if(qr>mid)update(rc,ql,qr,v);
		pushup(p);
	}
	inline Val query(int p,int ql,int qr){
		if(ql<=T[p].l&&T[p].r<=qr)return T[p].val;
		pushdown(p);
		Val ret=val_empty;
		if(ql<=mid)ret+=query(lc,ql,qr);
		if(qr>mid)ret+=query(rc,ql,qr);
		return ret;
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
	for(ri i=0;i<100;++i)SGT::val_empty[i]=0;
	n=read(),m=read();
	for(ri i=1;i<=n;++i)scanf("%lf",&a[i]);
	SGT::build(1,1,n);
	double x;
	for(ri l,r,op;m;--m){
		op=read(),l=read(),r=read();
		if(!op)printf("%.8lf\n",exp(SGT::solve2(SGT::query(1,l,r))));
		else scanf("%lf",&x),SGT::update(1,l,r,(SGT::Tag){x});
	}
	return 0;
}

2019.02.14 codechef Chef at the Food Fair(线段树+泰勒展开)的更多相关文章

  1. 2019.02.28 bzoj4199: [Noi2015]品酒大会(sam+线段树)

    传送门 题意:给一个串,每个位置有一个权值,当S[s...s+len−1]=S[t...t+len−1]&&S[s...s+len]̸=S[t..t+len]S[s...s+len-1 ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  3. 2019.02.15 codechef Favourite Numbers(二分+数位dp+ac自动机)

    传送门 题意: 给444个整数L,R,K,nL,R,K,nL,R,K,n,和nnn个数字串,L,R,K,数字串大小≤1e18,n≤65L,R,K,数字串大小\le1e18,n\le65L,R,K,数字 ...

  4. 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair

    第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...

  5. CodeChef DISTNUM2 Easy Queries 节点数组线段树

    Description You are given an array A consisting of N positive integers. You have to answer Q queries ...

  6. UVAlive7141 BombX 14年上海区域赛D题 线段树+离散化

    题意:一个无限大的棋盘, 有n个小兵, 给出了n个兵的坐标, 现在有一个长为width 高为height的炸弹放在棋盘上, 炸弹只能上下左右平移, 不能旋转. 且放炸弹的区域不能含有士兵, 炸弹可以一 ...

  7. 2019.01.22 bzoj3333: 排队计划(逆序对+线段树)

    传送门 题意简述:给出一个序列,支持把ppp~nnn中所有小于等于apa_pap​的'扯出来排序之后再放回去,要求动态维护全局逆序对. 思路:我们令fif_ifi​表示第iii个位置之后比它大的数的个 ...

  8. 2019.01.13 loj#6515. 贪玩蓝月(线段树分治+01背包)

    传送门 题意简述:有一个初始为空的双端队列,每次可以在队首和队尾插入或弹出一个二元组(wi,vi)(w_i,v_i)(wi​,vi​),支持询问从当前队列中选取若干个元素是的他们的和对 MODMODM ...

  9. 2019.01.13 bzoj4137: [FJOI2015]火星商店问题(线段树分治+可持久化01trie)

    传送门 题意:序列上有nnn个商店,有两种事件会发生: sss商店上进购标价为vvv的一个物品 求编号为[l,r][l,r][l,r]之间的位置买ddd天内新进购的所有物品与一个数xxx异或值的最大值 ...

随机推荐

  1. RE validator

    package com.office.utility;   import java.util.regex.Pattern;   /**  * 校验器:利用正则表达式校验邮箱.手机号等  *  * @a ...

  2. 配置gitlab自动备份

    在gitlab机器的root用户执行 首先,假设有2台机器. gitlab 1.1.1.1 backup 2.2.2.2 做秘钥信任 gitlab root 生成 ssh-key copy密钥到bac ...

  3. 关于java和jvm的思考

    1. 多线程并发访问一个静态方法(static method)会不会有什么性能影响? 思考:不会,原因是static method编译后及时一串指令(jvm中的静态方法区,也叫non-heap(包含了 ...

  4. 剑指offer题目解答合集(C++版)

    数组中重复的数字 二维数组中查找 字符串 替换空格 二叉树的编码和解码 从尾到头打印链表 重建二叉树 二叉树的下一个节点 2个栈实现队列 斐波那契数列 旋转数字 矩阵中的路径 机器人的运动范围 剪绳子 ...

  5. [python,2018-03-06] python中的继承顺序

    python 支持多继承,但对与经典类和新式类来说,多继承查找的顺序是不一样的.  经典类: 新式类   class P1:      def foo(self):                   ...

  6. vs与linux的交叉编译环境搭建

    很久之前就想写一个linux服务器,但是对linux的vim编译工具又不是很熟,只能在win环境下写好代码拷贝到linux环境下编译运行,现在VS出了一个插件可以对linux代码远程在linux环境下 ...

  7. 深入理解volatile

    volatile知识点 --------------------------------------------------------------------------- 1.volatile关键 ...

  8. 解决strcmp的错误以及VS的快捷键

    主要是C++数组作业中发现的一些问题. 第一点是关于strcat函数 我用VS2018调用strcat的时候报错,错误信息提示strcat不安全(?)要用strcat_s.修改后,可成功运行. 但这两 ...

  9. IntelliJ IDEA 导入多个maven项目

    IntelliJ IDEA的功能十分强大  我们日常开发项目会分多个maven项目 idea单个打开切换很是麻烦 下边是idea可以同时导入多个项目的方法 1.选择 FIle -> NEW -& ...

  10. 新部署tomcat,An error occurred at line: [1] index_jsp.java

    环境: centos6.5 32位 oracle jdk 1.8 tomcat 7 问题: yum install tomcat后,返回如下错误: [root@centos]~# curl -v ht ...