这题挺简单的 不过错的很玄学
用公式 sin(a+x)=sina*cosx+sinx*cosa cos(a+x)=cosa*cosx-sina*sinx就行 维护sinx的和和cosx的和更新就行了 需要注意的是常数比较大 三角函数的值尽量只算一次 传递下去就行 然后玄学的地方是 我把lazy[x]+=val;放到cal函数里面会wa 把它单独拿出来写就能过 不知道为什么
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define Ri register int
#define ls id<<1
#define rs ls|1
#define lson ls,l,mid
#define rson rs,mid+1,r
using namespace std;
const int N = 2e5+10;
typedef long long ll;
double sine[N<<2],cosi[N<<2];
int a[N];
ll lazy[N<<2];
inline int in(){
Ri w=0,x=0;char c=0;
while(c>'9'||c<'0') w|=c=='-',c=getchar();
while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return w?-x:x;
}
inline void pushup(int id){
sine[id] = sine[ls]+sine[rs];
cosi[id] = cosi[ls]+cosi[rs];
}
inline void cal(Ri x,double sinv,double cosv){
double sina=sine[x],cosa=cosi[x];
sine[x]=sina*cosv+cosa*sinv;
cosi[x]=cosa*cosv-sina*sinv;
}
inline void pushdown(Ri id){
if(lazy[id]){
double sinv=sin(lazy[id]),cosv=cos(lazy[id]);
cal(ls,sinv,cosv);
cal(rs,sinv,cosv);
lazy[ls]+=lazy[id];
lazy[rs]+=lazy[id];
lazy[id]=0;
}
}
void build(Ri id,Ri l,Ri r){
if(l==r){
sine[id]=sin(a[l]);
cosi[id]=cos(a[l]);
return;
}
int mid = l+r>>1;
build(lson);build(rson);
pushup(id);
}
void update(Ri id,Ri l,Ri r,Ri L,Ri R,Ri val){
if(L<=l&&R>=r){
cal(id,sin(val),cos(val));
lazy[id]+=val;
return;
}
pushdown(id);
int mid = l+r>>1;
if(L<=mid) update(lson,L,R,val);
if(R>mid) update(rson,L,R,val);
pushup(id);
}
double query(Ri id,Ri l,Ri r,Ri L,Ri R){
if(L<=l&&R>=r){
return sine[id];
}
int mid = l+r>>1;
double ret = 0;
pushdown(id);
if(L<=mid) ret+=query(lson,L,R);
if(R>mid) ret+=query(rson,L,R);
return ret;
}
int main(){
int n;
n=in();
for(int i = 1; i <= n; i++) a[i]=in();
build(1,1,n);
int m;
scanf("%d",&m);
for(Ri i = 1; i <= m; i++){
Ri op,l,r,x;
op=in();
if(op==1){
l=in(),r=in(),x=in();
update(1,1,n,l,r,x);
}else{
l=in(),r=in();
printf("%.1lf\n",query(1,1,n,l,r));
}
}
return 0;
}