[线段树]P6327 区间加区间 sin 和 题解
实际上知道了和差角公式这个题就好做了。
\[\sin(\alpha + \beta) = \sin(\alpha) \cos (\beta) + \cos(\alpha)\sin(\beta)
\]
\[\cos(\alpha + \beta) = \cos(\alpha)\cos(\beta) - \sin(\alpha)\sin(\beta)
\]
然后想一下怎么推到多个 \(\sin\) 的和。我们先不管第二个式子,只看第一个式子,看第一项,然后发现 \(\cos(\beta)\) 是个常量,那么直接乘法分配律就行。
其他同理。
\[\sum \sin (\alpha + \beta) = \cos(\beta)\sum \sin(\alpha) + \sin(\beta)\sum \cos(\alpha)
\]
因此维护区间 \(\sin\) 与 \(\cos\) 的和就行。还有就是要维护一下区间加的 \(lazy\) \(tag\)方便下传标记。
把下传的代码放一下吧。
void pushdown(int i) {
if(plz[i]) {
//Sin是区间sin和 , Cos是区间cos和 ,plz是加法的lazytag
double s1 = Sin[i << 1] , c1 = Cos[i << 1];
Sin[i << 1] = s1 * cos(plz[i]) + c1 * sin(plz[i]);
Cos[i << 1] = c1 * cos(plz[i]) - s1 * sin(plz[i]);
s1 = Sin[i << 1 | 1] , c1 = Cos[i << 1 | 1];
Sin[i << 1 | 1] = s1 * cos(plz[i]) + c1 * sin(plz[i]);
Cos[i << 1 | 1] = c1 * cos(plz[i]) - s1 * sin(plz[i]);
plz[i << 1] += plz[i];
plz[i << 1 | 1] += plz[i];
plz[i] = 0;
}
}