洛谷 U141387 金

洛谷 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;
}
原文地址:https://www.cnblogs.com/fusiwei/p/14025537.html