链接:https://ac.nowcoder.com/acm/contest/160/D?&headNav=www
来源:牛客网
题目描述
给出一个长度为n的整数序列a1,a2,...,an,进行m次操作,操作分为两类。
操作1:给出l,r,v,将al,al+1,...,ar分别加上v;
操作2:给出l,r,询问∑i=lrsin(ai)\sum\limits_{i=l}^{r}sin(a_i)i=l∑rsin(ai)
输入描述:
第一行一个整数n 接下来一行n个整数表示a1,a2,...,an 接下来一行一个整数m 接下来m行,每行表示一个操作,操作1表示为1 l r v,操作2表示为2 l r 保证1≤n,m,ai,v≤200000;1≤l≤r≤n,v是整数
输出描述:
对每个操作2,输出一行,表示答案,四舍五入保留一位小数 保证答案的绝对值大于0.1,且答案的准确值的小数点后第二位不是4或5 数据随机生成(n,m人工指定,其余整数在数据范围内均匀选取),并去除不满足条件的操作2
示例1
输入
4 1 2 3 4 5 2 2 4 1 1 3 1 2 2 4 1 2 4 2 2 1 3
输出
0.3 -1.4 -0.3
思路:根据sin(a+v)=sin(a)cos(v)+cos(a)sin(v),cos(a+v)=cos(a)cos(v)-sin(a)sin(v)维护即可。注意一点,cmath中求sin,cos还是挺慢的,写法有问题会T。。。
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=2e5+10;
const double eps=1e-8;
double a[maxn];
struct node{
int l;
int r;
double laz;
double sumcos;
double sumsin;
}tree[maxn<<2];
int n,m;
void pushup(int cur)
{
tree[cur].sumsin=tree[cur<<1].sumsin+tree[cur<<1|1].sumsin;
tree[cur].sumcos=tree[cur<<1].sumcos+tree[cur<<1|1].sumcos;
}
void pushdown(int cur)
{
double sinval,cosval,tsin,tcos;
if(fabs(tree[cur].laz)>eps)
{
sinval=sin(tree[cur].laz),cosval=cos(tree[cur].laz);
tsin=tree[cur<<1].sumsin,tcos=tree[cur<<1].sumcos;
tree[cur<<1].sumsin=tsin*cosval+tcos*sinval;
tree[cur<<1].sumcos=tcos*cosval-tsin*sinval;
tree[cur<<1].laz+=tree[cur].laz;
tsin=tree[cur<<1|1].sumsin,tcos=tree[cur<<1|1].sumcos;
tree[cur<<1|1].sumsin=tsin*cosval+tcos*sinval;
tree[cur<<1|1].sumcos=tcos*cosval-tsin*sinval;
tree[cur<<1|1].laz+=tree[cur].laz;
tree[cur].laz=0.0;
}
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
tree[cur].laz=0.0;
if(l==r)
{
tree[cur].sumsin=sin(a[l]);
tree[cur].sumcos=cos(a[l]);
return ;
}
int m=(l+r)>>1;
build(l,m,cur<<1);
build(m+1,r,cur<<1|1);
pushup(cur);
}
void update(int L,int R,double val,int cur)
{
double sinval,cosval,tsin,tcos;
if(L<=tree[cur].l&&tree[cur].r<=R)
{
sinval=sin(val),cosval=cos(val),tsin=tree[cur].sumsin,tcos=tree[cur].sumcos;
tree[cur].sumsin=tsin*cosval+tcos*sinval;
tree[cur].sumcos=tcos*cosval-tsin*sinval;
tree[cur].laz+=val;
return ;
}
pushdown(cur);
if(L<=tree[cur<<1].r) update(L,R,val,cur<<1);
if(R>tree[cur<<1].r) update(L,R,val,cur<<1|1);
pushup(cur);
}
double query(int L,int R,int cur)
{
if(L<=tree[cur].l&&tree[cur].r<=R) return tree[cur].sumsin;
double res=0.0;
pushdown(cur);
if(L<=tree[cur<<1].r) res+=query(L,R,cur<<1);
if(R>tree[cur<<1].r) res+=query(L,R,cur<<1|1);
return res;
}
int main()
{
int n,op,x,y;
double z;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lf",&x,&y,&z);
update(x,y,z,1);
}
if(op==2)
{
scanf("%d%d",&x,&y);
double ans=query(x,y,1);
printf("%.1lf\n",ans);
}
}
return 0;
}