codeforces 283A. Cows and Sequence [线段树-区间更新]

本文介绍了一种利用线段树解决动态序列操作问题的方法,包括区间加法、单点加法及删除操作,并详细展示了如何通过区间更新来优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

对一个初始有1个元素0的 序列进行三种动态操作:

1. 前k个元素都加X
2. 在序列后增加一个元素X
3. 删除序列最后一个元素

要求每次操作后输出序列的平均值,保证每次操作后队列至少有1个元素,操作数少于20 0000次

思路:注意第一种操作是对前k个元素都加X,而第三种操作是删除最后一个元素,那么不可能简单地模拟了。于是用线段树,这里用到区间更新。

第一种操作,对1~k 区间增加X。第二种操作对n+1~n+1区间增加X。第三种操作先查询n~n的和s,再对n~n个元素增加 -s。

区间更新需要增加新变量inc,如果inc不等于0,表示这段区间的所有子区间都增加inc*区间长度

#include <iostream>
#include <cstdio>
#define N 200005
typedef long long LL;
struct Node
{
	int a, b;
	LL sum, inc;
	Node() {}
	Node(int _a, int _b): a(_a), b(_b), sum(0), inc(0) {}
	int middle() { return (a+b)>>1; }
} t[N*4];
void build(int l, int r, int d)
{
	if (l > r) return ;
	t[d] = Node(l,r);
	if (l == r) return ;
	int mid = t[d].middle();
	build(l,mid,d<<1);
	build(mid+1,r,(d<<1)+1);
}
void update(int fo, int to, int v, int d)
{
	t[d].sum += (to-fo+1)*v;
	if (fo==t[d].a && t[d].b==to)
	{
		t[d].inc += v;
		return ;
	}
	int mid = t[d].middle();
	if (mid>=fo && mid<to)
	{
		update(fo,mid,v,d<<1);
		update(mid+1,to,v,(d<<1)+1);
	}
	else if (mid < fo)
	{
		update(fo,to,v,(d<<1)+1);
	}
	else if (mid >= to)
	{
		update(fo,to,v,d<<1);
	}
}
LL quary(int fo, int to, int d)
{
	if (fo==t[d].a && to==t[d].b) return t[d].sum;
	int mid = t[d].middle();
	if (mid>=fo && mid<to) return quary(fo,mid,d<<1) + quary(mid+1,to,(d<<1)+1) + (to-fo+1)*t[d].inc;
	else if (mid < fo) return quary(fo,to,(d<<1)+1) + (to-fo+1)*t[d].inc;
	else if (mid >= to) return quary(fo,to,d<<1) + (to-fo+1)*t[d].inc;
}
int n, m, tag;
int main()
{
	while (scanf("%d",&m) != EOF)
	{
		n = 1;
		build(1,m+1,1);
		while (m --)
		{
			scanf("%d",&tag);
			if (tag == 1)
			{
				int to, v;
				scanf("%d%d",&to,&v);
				update(1,to,v,1);
			}
			else if (tag == 2)
			{
				int v;
				n ++;
				scanf("%d",&v);
				update(n,n,v,1);
			}
			else
			{
				int v = int(quary(n,n,1));
				update(n,n,-v,1);
				n --;
			}
			printf("%.6lf\n", 1.0*quary(1,n,1)/n);
		}
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值