思路
显然用线段树做,但是如何维护修改操作呢?
设为线段树上节点所维护区间的值和,有,如果给区间加一个数字,原式变成
所以可以维护区间和,并维护一个标记,表示区间加了多少。下传标记时直接用标记的值维护子节点答案即可。
代码
#include<bits/stdc++.h>
#define lc p<<1
#define rc p<<1|1
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
/*#################################*/
const ll N=2E5+10;
ll n,q;
ll a[N],tag[4*N];
db sinx,cosx;
db ts[4*N],tc[4*N];
void update(ll p)
{
ts[p]=ts[lc]+ts[rc];
tc[p]=tc[lc]+tc[rc];
}
void build(ll p,ll l,ll r)
{
if(l==r)
{
ts[p]=sin(a[l]);
tc[p]=cos(a[l]);
return;
}
ll mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
update(p);
}
void flag(ll p,ll val,db sx,db cx)
{
db si=ts[p],co=tc[p];
ts[p]=(cx*si+sx*co);
tc[p]=(cx*co-sx*si);
tag[p]+=val;
}
void push_down(ll p)
{
db tmps=sin(tag[p]),tmpc=cos(tag[p]);
flag(lc,tag[p],tmps,tmpc);
flag(rc,tag[p],tmps,tmpc);
tag[p]=0;
}
void modify(ll p,ll l,ll r,ll al,ll ar,ll val)
{
if(al<=l && ar>=r)
{
flag(p,val,sinx,cosx);
return;
}
ll mid=(l+r)>>1;
if(tag[p])
push_down(p);
if(al<=mid)
modify(lc,l,mid,al,ar,val);
if(ar>mid)
modify(rc,mid+1,r,al,ar,val);
update(p);
}
db query(ll p,ll l,ll r,ll al,ll ar)
{
if(al<=l && ar>=r)
return ts[p];
ll mid=(l+r)>>1;
db ret=0;
if(tag[p])
push_down(p);
if(al<=mid)
ret+=query(lc,l,mid,al,ar);
if(ar>mid)
ret+=query(rc,mid+1,r,al,ar);
return ret;
}
int main()
{
read(n);
rep(i,1,n)
read(a[i]);
read(q);
build(1,1,n);
ll ty,l,r,x;
while(q--)
{
read(ty,l,r);
if(ty==1)
{
read(x);
sinx=sin(x);
cosx=cos(x);
modify(1,1,n,l,r,x);
}
else
{
printf("%.1lf\n",query(1,1,n,l,r));
}
}
}