列表

详情


NC230525. 区间加区间sin和

描述

给出一个长度为 n 的整数序列 ,进行 m 次操作,操作分为两类。

操作 1:给出 l,r,v,将 分别加上 v

操作 2:给出 l,r,询问

输入描述

第一行一个整数 n

接下来一行 n 个整数表示

接下来一行一个整数 m

接下来 m 行,每行表示一个操作,操作 1 表示为 ,操作 2 表示为
保证 。保证所有输入的数都是正整数。

输出描述

对每个操作 $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;
}

上一题