NC230525. 区间加区间sin和
描述
输入描述
第一行一个整数 。
接下来一行 个整数表示 。
接下来一行一个整数 。
接下来 行,每行表示一个操作,操作 表示为 ,操作 表示为 。
保证 ,。保证所有输入的数都是正整数。
输出描述
对每个操作 $2$,输出一行,表示答案。误差不超过即为正确。
示例1
输入:
5 1 3 1 5 5 5 1 5 5 5 2 3 3 2 1 5 2 2 2 2 4 4
输出:
0.841471 0.321117 0.141120 -0.958924
C++(clang++ 11.0.1) 解法, 执行用时: 1224ms, 内存消耗: 20320K, 提交时间: 2023-08-09 20:22:40
#include<bits/stdc++.h> #define int long long using namespace std; const int N = 2e5+5; const int mod = 1e9+7; int arr[N]; double Sin[N<<2],Cos[N<<2]; int tag[N<<2]; void pushup(int x){ Sin[x]=Sin[x<<1]+Sin[x<<1|1]; Cos[x]=Cos[x<<1]+Cos[x<<1|1]; } void build(int l,int r,int x){ if(l==r){ Sin[x]=sin(arr[l]); Cos[x]=cos(arr[l]); return; } int mid=(l+r)>>1; build(l,mid,x<<1); build(mid+1,r,x<<1|1); pushup(x); } void modify(int x,int v){ double sina=Sin[x]; double cosa=Cos[x]; double sinb=sin(v); double cosb=cos(v); Sin[x]=sina*cosb+cosa*sinb; Cos[x]=cosa*cosb-sina*sinb; } void pushdown(int x){ if(!tag[x]) return; modify(x<<1,tag[x]); modify(x<<1|1,tag[x]); tag[x<<1]+=tag[x]; tag[x<<1|1]+=tag[x]; tag[x]=0; } void upd(int v,int L,int R,int l,int r,int x){ if(L<=l&&r<=R){ modify(x,v); tag[x]+=v; return; } pushdown(x); int mid=(l+r)>>1; if(L<=mid) upd(v,L,R,l,mid,x<<1); if(R>mid) upd(v,L,R,mid+1,r,x<<1|1); pushup(x); } double query(int L,int R,int l,int r,int x){ if(L<=l&&r<=R) return Sin[x]; int mid=(l+r)>>1; double res=0; pushdown(x); if(L<=mid) res+=query(L,R,l,mid,x<<1); if(R>mid) res+=query(L,R,mid+1,r,x<<1|1); pushup(x); return res; } signed main(void){ ios::sync_with_stdio(false);cin.tie(0); int n; cin>>n; for(int i=1;i<=n;i++) cin>>arr[i]; build(1,n,1); cout<<fixed<<setprecision(6); int m; cin>>m; while(m--){ int opt,l,r; cin>>opt>>l>>r; if(opt==1){ int v; cin>>v; upd(v,l,r,1,n,1); } else cout<<query(l,r,1,n,1)<<"\n"; } return 0; }