Ynoi2012 NOIP2015洋溢着希望

北战南征 提交于 2020-03-18 07:07:35

写篇博客纪念一下人生第一道\(YnOI\)

不过这个题确实是不复杂

Description

link

支持两种操作,区间加和区间 \(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();} 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!