写篇博客纪念一下人生第一道\(YnOI\)
不过这个题确实是不复杂
Description
支持两种操作,区间加和区间 \(sin\) 和
\(n,m \le 2 \times 10^5\)
Solution
\[Begin\]
我们看到三角函数,还有加法
还是比较明显地指向了和角公式
如果不会和角公式? 这个百度应该可以 $ Get $ 到
\(sin(a+b)=sin(a) cos(b)+cos(a)sin(b)\)
\(cos(a+b)=cos(a)cos(b)-sin(a)sin(b)\)
\(sin\) 和 \(cos\) 的都用库里的函数就行
我们维护一下每个点的 \(sin\) 和 \(cos\) 就可以了吧……
具体要这么写:
inline void push_up(int p,double ts,double tc) { double s=sinn(p),c=coss(p); sinn(p)=ts*c+tc*s; coss(p)=tc*c-ts*s; return ; } inline void spread(int p) { if(fl(p)) { fl(p<<1)+=fl(p); fl(p<<1|1)+=fl(p); double ts=sin(fl(p)),tc=cos(fl(p)); push_up(p<<1,ts,tc); push_up(p<<1|1,ts,tc); }return fl(p)=0,void(); }
(但是在其它函数里面是直接搞的左右和,没有用 \(Push_up\) )
\[Q.A.D.\]
\(P.S.\)博主知道是\(QED\)
Code
#include<bits/stdc++.h> using namespace std; #define int long long namespace yspm{ inline int read() { int res=0,f=1; char k; while(!isdigit(k=getchar())) if(k=='-') f=-1; while(isdigit(k)) res=res*10+k-'0',k=getchar(); return res*f; } const int N=2e5+10; struct node{ int l,r,fl; double sinn,coss; #define fl(p) t[p].fl #define l(p) t[p].l #define r(p) t[p].r #define sinn(p) t[p].sinn #define coss(p) t[p].coss }t[N<<2]; int n,a[N]; inline void build(int p,int l,int r) { l(p)=l; r(p)=r; if(l==r) return sinn(p)=sin(a[l]),coss(p)=cos(a[l]),void(); int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); sinn(p)=sinn(p<<1)+sinn(p<<1|1); coss(p)=coss(p<<1|1)+coss(p<<1); return ; } inline void push_up(int p,double ts,double tc) { double s=sinn(p),c=coss(p); sinn(p)=ts*c+tc*s; coss(p)=tc*c-ts*s; return ; } inline void spread(int p) { if(fl(p)) { fl(p<<1)+=fl(p); fl(p<<1|1)+=fl(p); double ts=sin(fl(p)),tc=cos(fl(p)); push_up(p<<1,ts,tc); push_up(p<<1|1,ts,tc); }return fl(p)=0,void(); } inline void change(int p,int l,int r,double sinn,double coss,int x) { if(l<=l(p)&&r(p)<=r) return push_up(p,sinn,coss),fl(p)+=x,void(); int mid=(l(p)+r(p))>>1; spread(p); if(l<=mid) change(p<<1,l,r,sinn,coss,x); if(r>mid) change(p<<1|1,l,r,sinn,coss,x); sinn(p)=sinn(p<<1)+sinn(p<<1|1); coss(p)=coss(p<<1|1)+coss(p<<1); return ; } inline double ask(int p,int l,int r) { if(l<=l(p)&&r(p)<=r) return sinn(p); spread(p); int mid=(l(p)+r(p))>>1; double ans=0; if(l<=mid) ans+=ask(p<<1,l,r); if(r>mid) ans+=ask(p<<1|1,l,r); return ans; } signed main() { n=read(); for(int i=1;i<=n;++i) a[i]=read(); build(1,1,n); int T=read(); while(T--) { int opt=read(),x=read(),y=read(),z; if(opt==1) z=read(),change(1,x,y,sin(z),cos(z),z); if(opt==2) printf("%.1lf\n",ask(1,x,y)); } return 0; } } signed main(){return yspm::main();}
来源:https://www.cnblogs.com/yspm/p/12515173.html