列表

详情


NC17877. 整数序列

描述

给出一个长度为n的整数序列a1,a2,...,an,进行m次操作,操作分为两类。
操作1:给出l,r,v,将al,al+1,...,ar分别加上v;
操作2:给出l,r,询问

输入描述

第一行一个整数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

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 680ms, 内存消耗: 18260K, 提交时间: 2023-05-04 21:42:26

#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
//bwjj,我真的好喜欢你啊,mua~,为了你,我要做445题
const int koishi=2e5+5;
int a[koishi];
complex<double> lazy[koishi<<2],tree[koishi<<2];
void build(int p,int l,int r)
{
    lazy[p]=complex<double> (1,0);
    if(l==r)
    {
        tree[p]={cos(a[l]),sin(a[l])};
        return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid),build(p<<1|1,mid+1,r);
    tree[p]=tree[p<<1]+tree[p<<1|1];
}
void pushdown(int p)
{
    lazy[p<<1]*=lazy[p],lazy[p<<1|1]*=lazy[p];
    tree[p<<1]*=lazy[p],tree[p<<1|1]*=lazy[p];
    lazy[p]=complex<double> (1,0);
}
void update(int p,int l,int r,int x,int y,complex<double> w)
{
    if(l>y||r<x) return;
    if(l>=x&&r<=y)
    {
        lazy[p]*=w;
        tree[p]*=w;
        return;
    }
    pushdown(p);
    int mid=(l+r)>>1;
    update(p<<1,l,mid,x,y,w),update(p<<1|1,mid+1,r,x,y,w);
    tree[p]=tree[p<<1]+tree[p<<1|1];
}
double ask(int p,int l,int r,int x,int y)
{
    if(l>y||r<x) return 0;
    if(l>=x&&r<=y)
    {
        return tree[p].imag();
    }
    pushdown(p);
    int mid=(l+r)>>1;
    return ask(p<<1,l,mid,x,y)+ask(p<<1|1,mid+1,r,x,y);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin>>n;
    for(int i=1;i<=n;++i) cin>>a[i];
    build(1,1,n);
    int m;
    cin>>m;
    while(m--)
    {
        int op,l,r,v;
        cin>>op;
        if(op==1)
        {
            cin>>l>>r>>v;
            update(1,1,n,l,r,complex<double> (cos(v),sin(v)));
        }
        if(op==2)
        {
            cin>>l>>r;
            printf("%.1lf\n",ask(1,1,n,l,r));
        }
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 536ms, 内存消耗: 18320K, 提交时间: 2018-08-21 14:46:33

#include <bits/stdc++.h>
using namespace std;
const int maxn=200003;
typedef complex<double> E;
int n,q;
int a[maxn];
E sum[maxn<<2];
E lz[maxn<<2];
void pushup(int u){
	sum[u]=sum[2*u]+sum[2*u+1];
}
void pushdown(int u){
	lz[2*u]*=lz[u];
	sum[2*u]*=lz[u];
	lz[2*u+1]*=lz[u];
	sum[2*u+1]*=lz[u];
	lz[u]=E(1,0);
}
void build(int u,int l,int r){
	lz[u]=E(1,0);
	if(l==r){
		sum[u]=E(cos(a[l]),sin(a[l]));
		return;
	}
	int mid=(l+r)/2;
	build(2*u,l,mid);
	build(2*u+1,mid+1,r);
	pushup(u);
}
void update(int u,int l,int r,int ql,int qr,E x){
	if(ql>r||qr<l)return ;
	if(ql<=l&&r<=qr){
		lz[u]*=x;
		sum[u]*=x;
		return;
	}
	int mid=(l+r)/2;
	pushdown(u);
	update(2*u,l,mid,ql,qr,x);
	update(2*u+1,mid+1,r,ql,qr,x);
	pushup(u);
}
double query(int u,int l,int r,int ql,int qr){
	if(ql>r||qr<l)return 0;
	if(ql<=l&&r<=qr){
		return sum[u].imag();
	}
	int mid=(l+r)/2;
	pushdown(u);
	return query(2*u,l,mid,ql,qr)+query(2*u+1,mid+1,r,ql,qr);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		int typ;
		scanf("%d",&typ);
		if(typ==1){
			int l,r,x;
			scanf("%d%d%d",&l,&r,&x);
			update(1,1,n,l,r,E(cos(x),sin(x)));
		}
		else {
			int l,r;
			scanf("%d%d",&l,&r);
			printf("%.1f\n",query(1,1,n,l,r));
		}
	}
}

上一题