玄关求条
查看原帖
玄关求条
637073
wujingfey楼主2024/10/25 10:15

样例过了,全 WA

/*
线段树求sin和

考虑如何用 lz tag 快速实现区间修改 sin
sin(a+b)=sin(a)cos(b)+cos(a)sin(b)
线段树记录 sum1,sum2 和 lz 
sum1:区间sin和
sum2:区间cos和
lz:这个区间每个数都加了lz
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
int n,m,a[N];
struct NODE{
	int l,r,lz;
	double sum1,sum2;
}tr[N<<2];
void push_up(int p){
	tr[p].sum1=tr[p<<1].sum1+tr[p<<1|1].sum1;
	tr[p].sum2=tr[p<<1].sum2+tr[p<<1|1].sum2;
}
void build(int p,int l,int r){
	tr[p].l=l, tr[p].r=r;
	if(l==r){
		tr[p].sum1 = sin(a[l]);
		tr[p].sum2 = cos(a[l]);
		return;
	}
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	push_up(p);
}
void f(int p,double s,double c){
	double s1=tr[p].sum1*c + tr[p].sum2*s;
	double s2=tr[p].sum2*c - tr[p].sum1*s;
	tr[p].sum1=s1;
	tr[p].sum2=s2;
}
void push_down(int p){
	if(tr[p].lz==0) return;
	double s=sin(tr[p].lz), c=cos(tr[p].lz);
	f(p<<1, s, c);
	f(p<<1|1, s, c);
	tr[p].lz=0;
}
void update(int p,int nl,int nr,int k){
	if(nl<=tr[p].l && tr[p].r<=nr){
		double s=sin(k), c=cos(k);
		f(p, s, c);
		return;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	push_down(p);
	if(nl<=mid) update(p<<1,nl,nr,k);
	if(mid<nr) update(p<<1|1,nl,nr,k);
	push_up(p);
}
double query(int p,int nl,int nr){
	if(nl<=tr[p].l && tr[p].r<=nr){
		return tr[p].sum1;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	push_down(p);
	double res=0;
	if(nl<=mid) res+=query(p<<1,nl,nr);
	if(mid<nr) res+=query(p<<1|1,nl,nr); 
	return res;
}
signed main(){
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]); 
	}
	build(1,1,n);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int op,x,y,z;
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d%d",&x,&y,&z);
			update(1,x,y,z);
		}else{
			scanf("%d%d",&x,&y);
			printf("%.1lf\n",query(1,x,y));
		}
	}
	return 0;
}
2024/10/25 10:15
加载中...