codeforces 283A
introduction
这道题目的难点在于怎么在维护队列末尾的元素
method
看了官方的题解,我还是云里雾里的,最后经大神的题解点拨,才发现这道题目运用的是lazy思想。在学习线段树的时候遇到过这个思想,做这道题目的时候就没有想到,以后学习一定要透彻。
引用一下大神的解释:
A.比较简单,操作时候一直维护总和就可以了。。对于操作1(前a个数全部增加x)以及操作2(添加一个新数字在队列最后)显然可以顺利做到,而操作3则要求求出当前队列最后数字的值,我们可以用lasy的思想处理操作1即可以,如在head ~head+a 的位置增加x,我们可以在head+a的位置记录这个x(mark[head+ai]+=x),当head+a被删除之后后,才会要求求出head+ai-1位置的值,所以在删除head+a后我们将记录在该位置上的x值传到上一位即可(mark[head+a-1] += mark[head+a])..时间空间复杂度均O(n)
tips
- lazy技术应用的关键点在于属性值的变化在射线方向传播
- lazy数组要及时清零,或者说要保持正确的状态
Q&A
conclusion
一个算法往往体现了一种思想,不仅要学习算法的流程,更要体会算法的思想。
reference
http://www.cnblogs.com/lzqxh/archive/2013/03/19/2969723.html
code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<istream>
#include<cassert>
#include<set>
#include<iomanip>
#define DEBUG(x) cout<<#x<<" = "<<x<<endl
#define DEBUG2(x,y) cout<<#x<<" = "<<x<<" , "\
<<#y<<" = "<<y<<endl
using namespace std;
typedef long long ll;
const int MAXN=2e5+10;
double sum=0;
int pos=1;
int seq[MAXN];
///延迟技术
///在一个方向上变化的,容易实现延迟
int lazy[MAXN];
double delta(int op,int a,int x)
{
if(op==1){
lazy[a-1]+=x;
return a*x*1.0;
}
else if(op==2){
///lazy要清零
lazy[pos]=0;
seq[pos++]=a;
return a*1.0;
}
else {
pos--;
lazy[pos-1]+=lazy[pos];
seq[pos]+=lazy[pos];
return -seq[pos]*1.0;
}
}
int main()
{
// freopen("in.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF){
sum=0,pos=1;
memset(lazy,0,sizeof(lazy));
memset(seq,0,sizeof(seq));
while (n--){
int op=-1,a=-1,x=-1;
scanf("%d",&op);
if(op==1)scanf("%d%d",&a,&x);
else if(op==2)scanf("%d",&a);
sum+=delta(op,a,x);
printf("%.10lf\n",sum/pos);
}
}
}