[Ynoi2012]NOIP2015洋溢着希望 - 线段树

维护序列,支持区间加,区间求 \(\sum \sin(a_i)\)

Solution

考虑到 \(\sin(a+x)=\sin(a)\cos(x)+\cos(a)\sin(x)\)\(\cos\) 类似

于是我们可以对每个结点维护 \(\sum a,\sum \sin, \sum \cos\) 以及懒标记 \(tag\)

#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

#define int long long
const int N = 1000005;

int n,m,a[N],t1,t2,t3,t4;

double gsin(int t) {
    /*if(mps[t]) return mps[t];
    return mps[t]=sin(t);*/
    return sin(t);
}

double gcos(int t) {
    /*if(mpc[t]) return mpc[t];
    return mpc[t]=cos(t);*/
    return cos(t);
}

struct node {
    int a,t;
    double s,c=1;
} tr[N];

void put(int p,int x) {
    double s,c;
    double gc=gcos(x),gs=gsin(x);
    s=tr[p].s*gc+tr[p].c*gs;
    c=tr[p].c*gc-tr[p].s*gs;
    tr[p].s=s;
    tr[p].c=c;
    tr[p].t+=x;
}

void pushdown(int p) {
    if(tr[p].t) {
        put(p*2,tr[p].t);
        put(p*2+1,tr[p].t);
        tr[p].t=0;
    }
}

void pushup(int p) {
    tr[p].a=tr[p*2].a+tr[p*2+1].a;
    tr[p].s=tr[p*2].s+tr[p*2+1].s;
    tr[p].c=tr[p*2].c+tr[p*2+1].c;
}

void modify(int p,int l,int r,int ql,int qr,int x) {
    if(l>qr||r<ql) return;
    if(l>=ql&&r<=qr) {
        put(p,x);
    }
    else {
        pushdown(p);
        modify(p*2,l,(l+r)/2,ql,qr,x);
        modify(p*2+1,(l+r)/2+1,r,ql,qr,x);
        pushup(p);
    }
}

double query(int p,int l,int r,int ql,int qr) {
    if(l>qr||r<ql) return 0;
    if(l>=ql&&r<=qr) {
        return tr[p].s;
    }
    else {
        pushdown(p);
        return query(p*2,l,(l+r)/2,ql,qr)+
            query(p*2+1,(l+r)/2+1,r,ql,qr);
    }
}

void build(int p,int l,int r) {
    if(l==r) {
        put(p,a[l]);
    }
    else {
        build(p*2,l,(l+r)/2);
        build(p*2+1,(l+r)/2+1,r);
        pushup(p);
    }
}

signed main() {
    ios::sync_with_stdio(false);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    build(1,1,n);
    scanf("%lld",&m);
    for(int i=1;i<=m;i++) {
        scanf("%lld%lld%lld",&t1,&t2,&t3);
        if(t1==1) {
            scanf("%lld",&t4);
            modify(1,1,n,t2,t3,t4);
        }
        else {
            printf("%.1lf\n",query(1,1,n,t2,t3));
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12563044.html