洛谷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\n",qry(1,1,n,l,r));
    }
    return 0;
}

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

 +本文作者:luyouqi233。               +

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

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

posted @ 2019-08-29 14:26  luyouqi233  阅读(216)  评论(0编辑  收藏  举报