洛谷 U141387 金
题目背景
午睡过后,你——JDOI滴神,发现自己穿越到了一个陌生的机房里.....
你走进去,发现四台电脑的屏幕上分别印着四个大字:
“金” “智” “威” “!”
而黑板上写道:
“你的朋友$$JZW$$因出题太水受到了惩罚,现在他被关押于此,若想拯救他,你需要切掉他出的这四道水题”。
抱着一定要拯救出身为多项式之一的$$JZW$$的信念,你向着第一台电脑走去。
题目描述
一阵白光闪过,你被吸入了电脑中。
你来到了一个未知的王国。
询问得知,这个国王里的人痴迷于数学,对于理论研究已登峰造极。可他们有一个致命的缺陷——计算能力几乎为零。
你突然发现了墙上贴着的悬赏:
“能求出此序列之正弦函数者,赏黄金万两。”
你轻而易举地完成了这项挑战,但国王又不想白给这些黄金,于是他决定难为你一下。
国王共有$$m$$次操作,共有两种操作:
操作一:输入格式为$$1 l r v $$,表示从$$l$$到$$r$$的所有数字加上$$v$$
操作二:输入格式为$$2 l r $$,表示询问$$sum_{i=l}^rsin(a_i)$$
输入格式
从文件gold.ingol**d.i**n中读入数据。
第1行,一个整数N,表示序列长度。
第2行,N个整数,表示原序列$$a_i$$。
第3行,一个整数M,表示操作次数。
接下来M行,表示操作。
输出格式
输出到文件gold.outgol**d.out中。
输出每次询问的结果($$%.1f$$即可)
题解:
线段树裸题。
代码:
#include<cstdio>
#include<cmath>
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=2e5+5;
int n,m;
double a[maxn];
double cs[maxn<<2],sn[maxn<<2];
double lazy[maxn<<2];
void build(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
sn[pos]=sin(a[l]);
cs[pos]=cos(a[l]);
return;
}
build(lson,l,mid);
build(rson,mid+1,r);
sn[pos]=sn[lson]+sn[rson];
cs[pos]=cs[lson]+cs[rson];
}
void mark(int pos,int l,int r,double k)
{
double snn=sn[pos],css=cs[pos];
sn[pos]=(snn*cos(k)+css*sin(k));
cs[pos]=(css*cos(k)-snn*sin(k));
lazy[pos]+=k;
}
void pushdown(int pos,int l,int r)
{
int mid=(l+r)>>1;
mark(lson,l,mid,lazy[pos]);
mark(rson,mid+1,r,lazy[pos]);
lazy[pos]=0;
}
void update(int pos,int l,int r,int x,int y,double k)
{
int mid=(l+r)>>1;
if(x<=l && r<=y)
{
mark(pos,l,r,k);
return;
}
if(lazy[pos])
pushdown(pos,l,r);
if(x<=mid)
update(lson,l,mid,x,y,k);
if(y>mid)
update(rson,mid+1,r,x,y,k);
sn[pos]=sn[lson]+sn[rson];
cs[pos]=cs[lson]+cs[rson];
}
double query(int pos,int l,int r,int x,int y)
{
double ret=0;
int mid=(l+r)>>1;
if(x<=l && r<=y)
return sn[pos];
if(lazy[pos])
pushdown(pos,l,r);
if(x<=mid)
ret+=query(lson,l,mid,x,y);
if(y>mid)
ret+=query(rson,mid+1,r,x,y);
return ret;
}
int main()
{
// freopen("gold.in","r",stdin);
// freopen("gold.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int opt,x,y;
double v;
scanf("%d%d%d",&opt,&x,&y);
if(opt==1)
{
scanf("%lf",&v);
update(1,1,n,x,y,v);
}
else
printf("%.1lf
",query(1,1,n,x,y));
}
return 0;
}