维护序列,支持区间加,区间求 (sum sin(a_i))
Solution
考虑到 (sin(a+x)=sin(a)cos(x)+cos(a)sin(x)),(cos) 类似
于是我们可以对每个结点维护 (sum a,sum sin, sum cos) 以及懒标记 (tag)
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define int long long
const int N = 1000005;
int n,m,a[N],t1,t2,t3,t4;
double gsin(int t) {
/*if(mps[t]) return mps[t];
return mps[t]=sin(t);*/
return sin(t);
}
double gcos(int t) {
/*if(mpc[t]) return mpc[t];
return mpc[t]=cos(t);*/
return cos(t);
}
struct node {
int a,t;
double s,c=1;
} tr[N];
void put(int p,int x) {
double s,c;
double gc=gcos(x),gs=gsin(x);
s=tr[p].s*gc+tr[p].c*gs;
c=tr[p].c*gc-tr[p].s*gs;
tr[p].s=s;
tr[p].c=c;
tr[p].t+=x;
}
void pushdown(int p) {
if(tr[p].t) {
put(p*2,tr[p].t);
put(p*2+1,tr[p].t);
tr[p].t=0;
}
}
void pushup(int p) {
tr[p].a=tr[p*2].a+tr[p*2+1].a;
tr[p].s=tr[p*2].s+tr[p*2+1].s;
tr[p].c=tr[p*2].c+tr[p*2+1].c;
}
void modify(int p,int l,int r,int ql,int qr,int x) {
if(l>qr||r<ql) return;
if(l>=ql&&r<=qr) {
put(p,x);
}
else {
pushdown(p);
modify(p*2,l,(l+r)/2,ql,qr,x);
modify(p*2+1,(l+r)/2+1,r,ql,qr,x);
pushup(p);
}
}
double query(int p,int l,int r,int ql,int qr) {
if(l>qr||r<ql) return 0;
if(l>=ql&&r<=qr) {
return tr[p].s;
}
else {
pushdown(p);
return query(p*2,l,(l+r)/2,ql,qr)+
query(p*2+1,(l+r)/2+1,r,ql,qr);
}
}
void build(int p,int l,int r) {
if(l==r) {
put(p,a[l]);
}
else {
build(p*2,l,(l+r)/2);
build(p*2+1,(l+r)/2+1,r);
pushup(p);
}
}
signed main() {
ios::sync_with_stdio(false);
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
scanf("%lld",&m);
for(int i=1;i<=m;i++) {
scanf("%lld%lld%lld",&t1,&t2,&t3);
if(t1==1) {
scanf("%lld",&t4);
modify(1,1,n,t2,t3,t4);
}
else {
printf("%.1lf
",query(1,1,n,t2,t3));
}
}
}