P6327 区间加区间sin和
经典题,找bug找了半天,最后发现竟然是倍角公式写错了,有很多收获,宏定义减少代码量,update函数大大减少了代码量。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <sstream>
#define pb push_back
#define in insert
#define mem(f, x) memset(f,x,sizeof(f))
#define fo(i,a,n) for(int i=(a);i<=(n);++i)
#define fo_(i,a,n) for(int i=(a);i<(n);++i)
#define debug(x) cout<<#x<<":"<<x<<endl;
#define endl '\n'
using namespace std;
template<typename T>
ostream& operator<<(ostream& os,const vector<T>&v){for(int i=0,j=0;i<v.size();i++,j++)if(j>=5){j=0;puts("");}else os<<v[i]<<" ";return os;}
template<typename T>
ostream& operator<<(ostream& os,const set<T>&v){for(auto c:v)os<<c<<" ";return os;}
template<typename T1,typename T2>
ostream& operator<<(ostream& os,const map<T1,T2>&v){for(auto c:v)os<<c.first<<" "<<c.second<<endl;return os;}
typedef pair<int,int>PII;
typedef pair<long,long>PLL;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+10,M=1e9+7;
ll n,m;
double a[N];
struct Node
{
int l,r;
double sums,sumc;
ll tag;//sum(sin),sum(cos)
#define ls (p<<1)
#define rs (p<<1|1)
}t[N*4];
void pushup(int p){
t[p].sums=t[ls].sums+t[rs].sums;
t[p].sumc=t[ls].sumc+t[rs].sumc;
}
void build(int p,int l,int r)
{
t[p]={l,r};
if(l==r){
t[p].sums=sin(a[l]),t[p].sumc=cos(a[l]);
return ;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(p);
}
void update(int p,double sinx,double cosx){//秒啊
double sina=t[p].sums,cosa=t[p].sumc;
t[p].sums=cosx*sina+sinx*cosa;
t[p].sumc=cosx*cosa-sinx*sina;
}
void pushdown(int p)
{
if(t[p].tag){
double cosv=cos(t[p].tag),sinv=sin(t[p].tag);
update(ls,sinv,cosv);
update(rs,sinv,cosv);
t[ls].tag+=t[p].tag;
t[rs].tag+=t[p].tag;
t[p].tag=0;
}
}
void modify(int p,int tl,int tr,double x)
{
if(t[p].l>=tl&&t[p].r<=tr){
double cosv=cos(x),sinv=sin(x);
update(p,sinv,cosv);
t[p].tag+=x;
return ;
}
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(tl<=mid){
modify(ls,tl,tr,x);
}
if(tr>mid){
modify(rs,tl,tr,x);
}
pushup(p);
}
double query(int p,int tl,int tr)
{
if(t[p].l>=tl&&t[p].r<=tr){
return t[p].sums;
}
pushdown(p);
int mid=t[p].r+t[p].l>>1;
double res=0;
if(tl<=mid){
res+=query(ls,tl,tr);
}
if(tr>mid){
res+=query(rs,tl,tr);
}
return res;
}
int main()
{
cin>>n;
fo(i,1,n)scanf("%lf",&a[i]);
build(1,1,n);
cin>>m;
while(m--){
int l,r,k;
cin>>k>>l>>r;
if(k==2){
double t=query(1,l,r);
printf("%.1lf\n",t);
}
else{
double x;
cin>>x;
modify(1,l,r,x);
}
}
return 0;
}