zoukankan      html  css  js  c++  java
  • 洛谷5524:[Ynoi2012]NOIP2015洋溢着希望——题解

    https://www.luogu.org/problem/P5524

    看着能做就当线段树复健题了。

    根据高中知识我们有

    $sin(a+b)=sin(a)cos(b)+cos(a)sin(b)$

    $cos(a+b)=cos(a)cos(b)-sin(a)sin(b)$

    那这题只需要维护区间$sin$和与$cos$和的线段树就好了,完后区间加的更新方法如上。

    但是比较卡常,建议标记永久化,并且减少求$sincos$的次数。(反正我开O2过了就不管了233)

    ~~我真的是连线段树都不会敲了我乱push结果RE了debug了半天,难受555~~

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef double dl;
    const int N=2e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct tree{
        dl s,c;
        ll w;
    }tr[N<<2];
    int b[N];
    inline void pushup(int a){
        tr[a].s=tr[a<<1].s+tr[a<<1|1].s;
        tr[a].c=tr[a<<1].c+tr[a<<1|1].c;
        return;
    }
    inline void upd(int a,dl S,dl C){
        dl s=tr[a].s,c=tr[a].c;
        tr[a].s=s*C+c*S;
        tr[a].c=c*C-s*S;
        return;
    }
    inline void pushdown(int a){
        if(!tr[a].w)return;
        dl s=sin(tr[a].w),c=cos(tr[a].w); 
        upd(a<<1,s,c);upd(a<<1|1,s,c);
        tr[a<<1].w+=tr[a].w;tr[a<<1|1].w+=tr[a].w;
        tr[a].w=0;return;
    }
    void build(int a,int l,int r){
        if(l==r){
            tr[a].s=sin(b[l]);tr[a].c=cos(b[l]);return;
        }
        int mid=(l+r)>>1;
        build(a<<1,l,mid);build(a<<1|1,mid+1,r);
        pushup(a);
    }
    void add(int a,int l,int r,int l1,int r1,int v){
        if(r<l1||r1<l)return;
        if(l1<=l&&r<=r1){
            upd(a,sin(v),cos(v));tr[a].w+=v;return;
        }
        int mid=(l+r)>>1;pushdown(a);
        add(a<<1,l,mid,l1,r1,v);add(a<<1|1,mid+1,r,l1,r1,v);
        pushup(a);
    }
    dl qry(int a,int l,int r,int l1,int r1){
        if(r<l1||r1<l)return 0;
        if(l1<=l&&r<=r1)return tr[a].s;
        int mid=(l+r)>>1;pushdown(a);
        return qry(a<<1,l,mid,l1,r1)+qry(a<<1|1,mid+1,r,l1,r1);
    }
    int main(){
        int n=read();
        for(int i=1;i<=n;i++)b[i]=read();
        build(1,1,n);
        int m=read();
        while(m--){
            int op=read(),l=read(),r=read();
            if(op==1){
                int v=read();
                add(1,1,n,l,r,v);
            }else printf("%.1lf
    ",qry(1,1,n,l,r));
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    Java动态代理(三)——模拟AOP实现
    Java动态代理(二)CGLIB动态代理应用
    Java动态代理(一)动态类Proxy的使用
    CGLIB实现动态代理
    初识Java微信公众号开发
    spring+ibatis事务管理配置
    什么是事务的传播特性
    Spring事务配置的五种方式
    Java语言基础(五) Java原始数据类型的分类以及数据范围
    Java语言基础(四) String和StringBuffer的区别
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/11429503.html
Copyright © 2011-2022 走看看