1. 程式人生 > 其它 >P6327 區間加區間sin和(題解)

P6327 區間加區間sin和(題解)

思路:根據\(sin\)\(cos\)的運算來做。我們有:

\[sin(a+b) = sin(a) * cos(b) + sin(b)*cos(a) \]\[cos(a+b) = cos(a) * cos(b) - sin(a) * sin(b) \]

所以線段樹維護每個節點的\(sin\)\(cos\) 就能得到答案,需要注意的是懶標記應開\(longlong\)

\(Code:\)


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define ch() getchar()
#define pc(x) putchar(x)
#define rep(i, a, b) for (auto i = a; i <= b; ++i)
#define bep(i, a, b) for (auto i = a; i >= b; --i)
#define lowbit(x) x &(-x)
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define PI acos(-1)
using namespace std;
template <typename T>
void read(T &x) {
    static char c;
    static int f;
    for (c = ch(), f = 1; c < '0' || c > '9'; c = ch())
        if (c == '-') f = -f;
    for (x = 0; c >= '0' && c <= '9'; c = ch()) x = x * 10 + (c & 15);
    x *= f;
}
template <typename T>
void write(T x) {
    static char q[65];
    int cnt = 0;
    if (x < 0) pc('-'), x = -x;
    q[++cnt] = x % 10, x /= 10;
    while (x) q[++cnt] = x % 10, x /= 10;
    while (cnt) pc(q[cnt--] + '0');
}
const int N = 2e5 + 10;
int n;
int a[N];
struct segmentTree {
    struct node {
        int l, r, L, R;
        ll add;
        double sina, cosa;
    } tr[N << 3];
    inline void update(int u, double sinx, double cosx) {
        double sins = tr[u].sina, coss = tr[u].cosa;
        tr[u].sina = sins * cosx + coss * sinx;
        tr[u].cosa = coss * cosx - sins * sinx;
    }

    inline void pushup(int p) {
        tr[p].sina =
            tr[tr[p].l].sina +
            tr[tr[p].r].sina;  // +
                               //  tr[tr[p].r].sina * tr[tr[p].l].cosa);
        tr[p].cosa = tr[tr[p].l].cosa + tr[tr[p].r].cosa;
    }
    inline void pushdown(int p) {
        if (tr[p].add != 0) {
            ll d = tr[p].add;
            tr[p].add = 0;
            double rs = tr[tr[p].r].sina, ls = tr[tr[p].l].sina;
            (tr[tr[p].r].sina =
                 sin(d) * tr[tr[p].r].cosa + tr[tr[p].r].sina * cos(d));
            (tr[tr[p].r].cosa = cos(d) * tr[tr[p].r].cosa - rs * sin(d));
            (tr[tr[p].l].sina =
                 sin(d) * tr[tr[p].l].cosa + tr[tr[p].l].sina * cos(d));
            (tr[tr[p].l].cosa = cos(d) * tr[tr[p].l].cosa - ls * sin(d));
            (tr[tr[p].l].add += d);
            (tr[tr[p].r].add += d);
        }
    }
    inline void build(int l, int r, int p) {
        tr[p].l = p << 1;
        tr[p].r = p << 1 | 1;
        tr[p].L = l, tr[p].R = r;
        tr[p].add = 0;
        if (l == r) {
            tr[p].sina = sin(a[l]), tr[p].add = 0;
            tr[p].cosa = cos(a[l]);
            // printf("%d %d  %.3lf\n", tr[p].L, tr[p].R, tr[p].sina);
            return;
        }
        int mid = l + r >> 1;
        build(l, mid, tr[p].l), build(mid + 1, r, tr[p].r);
        pushup(p);
        // printf("%d %d %.1lf\n",tr[p].L,tr[p].R,tr[p].sina);
    }
    inline void add(int l, int r, int p, int k) {
        if (tr[p].L >= l && tr[p].R <= r) {
            double ps = tr[p].sina;
            tr[p].sina = tr[p].sina * cos(k) + tr[p].cosa * sin(k);
            tr[p].cosa = tr[p].cosa * cos(k) - ps * sin(k);
            tr[p].add += k;
            return;
        }
        pushdown(p);
        if (tr[tr[p].l].R >= l) add(l, r, tr[p].l, k);
        if (tr[tr[p].r].L <= r) add(l, r, tr[p].r, k);
        pushup(p);
    }
    inline double  ask(int l, int r, int p) {
        double ret = 0.0;
        pushdown(p);
        if (tr[p].L >= l && tr[p].R <= r) {
            // printf("~~%.1lf %.1lf\n", tr[p].sina, tr[p].cosa);
            return tr[p].sina;
        }
        if (tr[tr[p].l].R >= l) {
            (ret = ask(l, r, tr[p].l));
            // printf("~##!!!%d %d %.1lf\n", tr[p].L, tr[p].R, ret.first);
        }
        if (tr[tr[p].r].L <= r) {
            ret += ask(l,r,tr[p].r);
            // printf("~#!!!%d %d %.1lf\n", tr[p].L, tr[p].R, ret.first);
        }
        // printf("~!!!%d %d %.1lf\n", tr[p].L, tr[p].R, ret.first);
        return ret;
    }
} T;
int q;
void solve() {
    read(n);
    rep(i, 1, n) read(a[i]);
    T.build(1, n, 1);
    // printf("%.1lf\n", T.ask(3, 3, 1).first);
    read(q);
    while (q--) {
        int v, op, l, r;
        read(op);
        read(l);
        read(r);
        if (op == 1) {
            read(v);
            T.add(l, r, 1, v);
        } else {
            printf("%.1lf\n", T.ask(l, r, 1));
        }
    }
}
signed main(int argc, char const *argv[]) {
    solve();
    return 0;
}