萌新求助:关于精度问题
查看原帖
萌新求助:关于精度问题
468657
lsj2009Isj2OO9楼主2023/11/16 23:33

rt.

这个题大概来说就是要支持区间乘一个浮点数、然后最后查每个位置的值。

我最开始的写法是直接差分,在 ll 位置乘上 vv,在 r+1r+1 位置除上 vv,然后做个前缀积。

同时开个数组特判一下这个位置是否有被 00 覆盖过。

但是这个样子会喜提 Wrong Answer on test 12。

code:

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define ull unsigned long long
#define ld long double
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define chkmax(a,b) a=max(a,b)
#define chkmin(a,b) a=min(a,b)
#define rep(k,l,r) for(int k=l;k<=r;++k)
#define per(k,r,l) for(int k=r;k>=l;--k)
#define cl(f,x) memset(f,x,sizeof(f))
using namespace std;
const int N=1e6+5;
const ld eps=1e-9;
ld d[N],l[N],r[N];
int t[N],a[N],b[N],s[N],c[N],h[N],len;
int get_id(int x) {
	return lower_bound(t+1,t+len+1,x)-t;
}
void upd(int l,int r,ld val) {
	if(fabs(val)>eps) {
		d[l]*=val;
		d[r+1]/=val;
	} else {
		++s[l];
		--s[r+1];
	}
}
void solve() {
	int n,m;
	scanf("%d%d",&n,&m);
	rep(i,1,n) {
		scanf("%d%d%Lf%Lf",&a[i],&h[i],&l[i],&r[i]);
		l[i]/=100.0; r[i]/=100.0;
		t[++len]=a[i];
		t[++len]=a[i]-h[i];
		t[++len]=a[i]+h[i];
	}
	rep(i,1,m) {
		scanf("%d%d",&b[i],&c[i]);
		t[++len]=b[i];
	}
	sort(t+1,t+len+1);
	len=unique(t+1,t+len+1)-t-1;
	rep(i,0,len+1)
		d[i]=1.0;
	rep(i,1,n) {
		int _l=get_id(a[i]-h[i]),p=get_id(a[i]),_r=get_id(a[i]+h[i]);
		upd(_l,p-1,1.0-l[i]);
		upd(p+1,_r,1.0-r[i]);
	}
	rep(i,1,len) {
		d[i]*=d[i-1];
		s[i]+=s[i-1];
	}
	ld res=0;
	rep(i,1,m) {
		int x=get_id(b[i]);
		if(!s[x])
			res+=d[x]*c[i];
	}
	printf("%.9Lf\n",res);
}
signed main() {
	int testcase=1;
	//scanf("%d",&testcase);
	while(testcase--)
		solve();
	return 0;
}

然后我又改成了在 ll 处加 ln⁡v\ln{v},在 r+1r+1 处减 ln⁡v\ln{v},然后前缀和处理,再取 exp⁡\exp 就过了/yiw

code:

#include<bits/stdc++.h>
//#define int long long
#define ll long long
#define ull unsigned long long
#define ld long double
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define chkmax(a,b) a=max(a,b)
#define chkmin(a,b) a=min(a,b)
#define rep(k,l,r) for(int k=l;k<=r;++k)
#define per(k,r,l) for(int k=r;k>=l;--k)
#define cl(f,x) memset(f,x,sizeof(f))
using namespace std;
const int N=1e6+5;
const ld eps=1e-9;
ld d[N],l[N],r[N];
int t[N],a[N],b[N],s[N],c[N],h[N],len;
int get_id(int x) {
	return lower_bound(t+1,t+len+1,x)-t;
}
void upd(int l,int r,ld val) {
	if(fabs(val)>eps) {
		d[l]+=log(val);
		d[r+1]-=log(val);
	} else {
		++s[l];
		--s[r+1];
	}
}
void solve() {
	int n,m;
	scanf("%d%d",&n,&m);
	rep(i,1,n) {
		scanf("%d%d%Lf%Lf",&a[i],&h[i],&l[i],&r[i]);
		l[i]/=100.0; r[i]/=100.0;
		t[++len]=a[i];
		t[++len]=a[i]-h[i];
		t[++len]=a[i]+h[i];
	}
	rep(i,1,m) {
		scanf("%d%d",&b[i],&c[i]);
		t[++len]=b[i];
	}
	sort(t+1,t+len+1);
	len=unique(t+1,t+len+1)-t-1;
	rep(i,0,len+1)
		d[i]=log(1.0);
	rep(i,1,n) {
		int _l=get_id(a[i]-h[i]),p=get_id(a[i]),_r=get_id(a[i]+h[i]);
		upd(_l,p-1,1.0-l[i]);
		upd(p+1,_r,1.0-r[i]);
	}
	rep(i,1,len) {
		d[i]+=d[i-1];
		s[i]+=s[i-1];
	}
	ld res=0;
	rep(i,1,m) {
		int x=get_id(b[i]);
		if(!s[x])
			res+=exp(d[x])*c[i];
	}
	printf("%.9Lf\n",res);
}
signed main() {
	int testcase=1;
	//scanf("%d",&testcase);
	while(testcase--)
		solve();
	return 0;
}

萌新求助这两种方法为什么会有这么大的精度差距/kel

2023/11/16 23:33
加载中...