区间加区间sin和
题目描述
题解
\(sin(x+v)=sinxcosv+cosxsinv\)
\(cos(x+v)=-sinxsinv+cosxcosv\)
所以
\[\begin{pmatrix}
sin(x+v)\\cos(x+v)
\end{pmatrix}=
\begin{pmatrix}
cosv&sinv\\-sinv&cosv
\end{pmatrix}\cdot
\begin{pmatrix}
sinx\\cosx
\end{pmatrix}\]
那么可以类似Sasha and Array在线段树上维护矩阵
点击查看代码
#include<functional>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<deque>
#define ll long long
using namespace std;
const int maxn=8e5+101;
const int MOD=1e9+7;
const int inf=2147483647;
ll read(){
ll x=0,f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
return x*f;
}
int n,m,a[maxn];
struct Matrix{
double a[2][2];
void init(){
a[0][0]=a[1][1]=1;
a[0][1]=a[1][0]=0;
}
void zero(){memset(a,0,sizeof(a));}
Matrix operator*(const Matrix& m2)const{
Matrix m;m.zero();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
m.a[i][j]+=a[i][k]*m2.a[k][j];
}
}
}
return m;
}
Matrix operator+(const Matrix& m2)const{
Matrix m;m.zero();
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
m.a[i][j]+=(a[i][j]+m2.a[i][j]);
}
}
return m;
}
Matrix operator^(ll y)const{
Matrix sum,x;sum.init();
memcpy(x.a,a,sizeof(a));
while(y){
if(y&1)sum=sum*x;
y>>=1;x=x*x;
}
return sum;
}
};
struct tree{
bool flag;
Matrix M,lz;
void init(){
M.zero();lz.init();flag=0;
}
}tr[maxn];
void add(int k,Matrix v){
tr[k].M=v*tr[k].M;
tr[k].lz=tr[k].lz*v;
return;
}
void pushdown(int k){
if(tr[k].flag){
tr[k].flag=0;
tr[k<<1].flag=1;add(k<<1,tr[k].lz);
tr[k<<1|1].flag=1;add(k<<1|1,tr[k].lz);
tr[k].lz.init();
}
return ;
}
void build(int k,int l,int r){
tr[k].init();
if(l==r){
tr[k].M.a[0][0]=sin(a[l]);
tr[k].M.a[1][0]=cos(a[l]);
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
tr[k].M=tr[k<<1].M+tr[k<<1|1].M;
return ;
}
double query(int k,int l,int r,int L,int R){
if(r<L || l>R)return 0;
if(L<=l && r<=R)return tr[k].M.a[0][0];
int mid=(l+r)>>1;pushdown(k);
return (query(k<<1,l,mid,L,R)+query(k<<1|1,mid+1,r,L,R));
}
void update(int k,int l,int r,int L,int R,Matrix v){
if(r<L || l>R)return ;
if(L<=l && r<=R){
tr[k].flag=1;add(k,v);
return ;
}
int mid=(l+r)>>1;pushdown(k);
update(k<<1,l,mid,L,R,v);update(k<<1|1,mid+1,r,L,R,v);
tr[k].M=tr[k<<1].M+tr[k<<1|1].M;
return ;
}
int main(){
n=read();for(int i=1;i<=n;i++)a[i]=read();build(1,1,n);
m=read();
for(int i=1;i<=m;i++){
int opt=read(),l=read(),r=read();
if(opt==1){
int v=read();
Matrix ss;
ss.a[0][0]=cos(v);ss.a[0][1]=sin(v);
ss.a[1][0]=-sin(v);ss.a[1][1]=cos(v);
update(1,1,n,l,r,ss);
}
else printf("%.4lf\n",query(1,1,n,l,r));
}
return 0;
}