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;
}
I‘m Stein, welcome to my blog