洛谷P6327 区间加区间sin和 题解
题目链接:洛谷P6327 区间加区间sin和 题解
题意:维护一个数据结构,支持
- 区间加 v v v
- 询问区间 ∑ i = 1 r sin a i \sum\limits_{i=1}^{r}\sin a_i i=1∑rsinai
注意到
sin
(
a
+
x
)
=
sin
a
cos
x
+
cos
a
sin
x
cos
(
a
+
x
)
=
cos
a
cos
x
−
sin
a
sin
x
\begin{aligned} \sin(a+x)&=\sin a\cos x+\cos a \sin x\\ \cos(a+x)&=\cos a\cos x-\sin a \sin x \end{aligned}
sin(a+x)cos(a+x)=sinacosx+cosasinx=cosacosx−sinasinx
直接维护即可两个量即可
注意点:
- 更新的时候拿之前更新过的sin去更新cos,爆零。
- 不开long long,爆零。
- 不下传标记,爆零。
可以适当卡卡常(逃
代码如下
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(2e5+15)
#define ls(at) (at<<1)
#define rs(at) (at<<1|1)
namespace FastIO
{
#define gc() readchar()
#define pc(a) putchar(a)
#define SIZ (int)(1e6+15)
char buf1[SIZ],*p1,*p2;
char readchar()
{
if(p1==p2)p1=buf1,p2=buf1+fread(buf1,1,SIZ,stdin);
return p1==p2?EOF:*p1++;
}
template<typename T>void read(T &k)
{
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
k=x*f;
}
template<typename T>void write(T k)
{
if(k<0){k=-k;pc('-');}
static T stk[66];T top=0;
do{stk[top++]=k%10,k/=10;}while(k);
while(top){pc(stk[--top]+'0');}
}
}using namespace FastIO;
// #define double long double
// const double eps=1e-15;
double sinx[N<<2],cosx[N<<2];
int tag[N<<2];
int n,m,a[N];
void push_up(int at)
{
sinx[at]=sinx[ls(at)]+sinx[rs(at)];
cosx[at]=cosx[ls(at)]+cosx[rs(at)];
}
void build(int l,int r,int at)
{
if(l==r)
{
sinx[at]=sin(a[l]);
cosx[at]=cos(a[l]);
return;
}
int mid=(l+r)>>1;
build(l,mid,ls(at));
build(mid+1,r,rs(at));
push_up(at);
}
void proc(int at,int k)
{
double sink=sin(k),cosk=cos(k);
double sina=sinx[at],cosa=cosx[at];
sinx[at]=sina*cosk+cosa*sink;
cosx[at]=cosa*cosk-sina*sink;
tag[at]+=k;
}
void push_down(int at)
{
int k=tag[at];
if(k)
{
proc(ls(at),k);
proc(rs(at),k);
tag[at]=0;
}
}
void update(int nl,int nr,int l,int r,int k,int at)
{
if(nl<=l&&r<=nr)
{
proc(at,k);
return;
}
int mid=(l+r)>>1;
push_down(at);
if(nl<=mid)update(nl,nr,l,mid,k,ls(at));
if(nr>mid)update(nl,nr,mid+1,r,k,rs(at));
push_up(at);
}
double query(int nl,int nr,int l,int r,int at)
{
if(nl<=l&&r<=nr)return sinx[at];
if(nl>r||nr<l)return 0;
push_down(at);
int mid=(l+r)>>1;
return query(nl,nr,l,mid,ls(at))+query(nl,nr,mid+1,r,rs(at));
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
// cout << fixed << setprecision(1);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
read(n);
for(int i=1; i<=n; i++)
read(a[i]);
build(1,n,1);
int Q;read(Q);
int op,l,r,v;
while(Q--)
{
read(op);read(l);read(r);
if(op==1){read(v);update(l,r,1,n,v,1);}
else printf("%.1lf\n",query(l,r,1,n,1));
}
return 0;
}
转载请说明出处