P6327 区间加区间sin和 - 三角函数和差公式 + 线段树

传送门
2个操作

  • \([l,r]\)的区间加上\(v\)
  • \(\sum_{i = l}^rsin(a_i)\)

根据三角函数和差公式

\[\begin{aligned} \sin (a+\beta) &=\sin \alpha \cos \beta+\cos \alpha \sin \beta \\ \cos (\alpha+\beta) &=\cos \alpha \cos \beta-\sin \alpha \sin \beta \\ \tan (\alpha+\beta) &=\frac{\tan \alpha+\tan \beta}{1-\tan \alpha \tan \beta} \end{aligned} \]

维护两个值,\(sin(),cos()\)表示这段区间的sin和以及区间的cos和
对于区间修改,直接采用这个公式即可
\(sin(a + c) = sina * cosc + cosa * sinc\)
\(sin(b + c) = sinb * cosc + cosb * sinc\)
那么如果对\(a\)\(b\)同时加c操作,那么和就是\(cosc(sina + sinb) + sinc(cosa + cosb)\)
而我们的sin就是维护sin的区间和,每次修改直接进行修改进行了,然后再弄一个lazy向下标记

#include <iostream>
#include <cstdio>
#include <cmath>
#define ll long long
using namespace std;
const int N = 2e5 + 5;
double a[N];
struct SegTree{
    struct Tree{
        int l, r;
        ll lazy;
        double co, si;
        #define l(p) tree[p].l
        #define r(p) tree[p].r
        #define lazy(p) tree[p].lazy
        #define co(p) tree[p].co
        #define si(p) tree[p].si
        #define lson p << 1
        #define rson p << 1 | 1
    } tree[N << 2];
    void pushup(int p){
        si(p) = si(lson) + si(rson);
        co(p) = co(lson) + co(rson);
    }
    void add(int p, double sinx, double cosx){
        double sina = si(p), cosa = co(p);
        si(p) = sina * cosx + cosa * sinx;
        co(p) = cosa * cosx - sina * sinx;
    }
    void pushdown(int p){
        if(lazy(p)) {
            lazy(lson) += lazy(p);
            lazy(rson) += lazy(p);
            double sinx = sin(lazy(p)), cosx = cos(lazy(p));
            add(lson, sinx, cosx);
            add(rson, sinx, cosx);
            lazy(p) = 0;
        }
    }
    void build(int p, int l, int r){
        l(p) = l, r(p) = r; lazy(p) = 0;
        si(p) = 0, co(p) = 0;
        if(l == r) {
            si(p) = sin(a[l]);
            co(p) = cos(a[l]);
            return ;
        }
        int mid = (l + r) >> 1;
        build(lson, l, mid);
        build(rson, mid + 1, r);
        pushup(p);
    }
    void change(int p, int l, int r, int x){
        if(l <= l(p) && r(p) <= r) {
            add(p, sin(x), cos(x));
            lazy(p) += x;
            return;
        }
        pushdown(p);
        int mid = (l(p) + r(p)) >> 1;
        if(l <= mid) change(lson, l, r, x);
        if(r > mid) change(rson, l, r, x);
        pushup(p);
    }
    double query(int p, int l, int r){
        if(l <= l(p) && r(p) <= r) {
            return si(p);
        }
        pushdown(p);
        int mid = (l(p) + r(p)) >> 1;
        double ans = 0;
        if(l <= mid) ans += query(lson, l, r);
        if(r > mid) ans += query(rson, l, r);
        return ans; 
    }
} seg;
int main(){
    int n;scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%lf", &a[i]);
    seg.build(1, 1, n);
    int m;scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int op, l, r, v;
        scanf("%d%d%d", &op, &l, &r);
        if(op == 1) scanf("%d", &v), seg.change(1, l, r, v);
        else printf("%.1lf\n", seg.query(1, l, r));
    }
    return 0;
}
posted @ 2020-10-03 14:27  Emcikem  阅读(206)  评论(0编辑  收藏  举报