题目链接:http://codeforces.com/problemset/problem/284/C
题目意思:给出3种操作:t = 1:在前 a 个数中每个数都加上x; t= 2:在数组末尾增加一个数k,数组长度相应增加1; t = 3:删除数组最后一个数,数组长度减少1。对于n次操作,都给出整个数组所有元素的平均值。
一开始看见题目意思那么容易懂,于是以为很容易做,错足14次,15次终于成功了。先是TLE(对操作2直接暴力循环加),后在Test 10 wa wa wa~~~,说误差超了,全部不知道是什么回事!
其实3个操作不需要都模拟出来,操作3是比较麻烦的,因为删除的数有可能经过 t = 1有所变化。所以很自然地想到要追踪当前要删除的数经过t = 1 时的改变,这样就需要开多一个数组来记录这些位置。
代码中标上“关键”那里是很重要的,代表要清除操作1对数组中最后一个数的处理,否则新的一轮操作1会累加这种操作,这样结果就不正确了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 2*1e5 + 5; 8 int a[maxn], mark[maxn]; 9 10 int main() 11 { 12 int n, i, t, x, l, len; 13 while (scanf("%d", &n) != EOF) 14 { 15 memset(mark, 0, sizeof(mark)); 16 a[len=1] = 0; 17 double sum = 0; 18 while (n--) 19 { 20 scanf("%d", &t); 21 if (t == 1) 22 { 23 scanf("%d%d", &l, &x); 24 sum += (double) l * x; 25 mark[l] += x; 26 } 27 else if (t == 2) 28 { 29 scanf("%d", &x); 30 sum += x; 31 a[++len] = x; 32 } 33 else 34 { 35 if (len >= 2) 36 { 37 sum -= a[len]; //减最后一个数 38 sum -= mark[len]; //减最后一个数经过操作1时可能的变化 39 mark[len-1] += mark[len]; 40 mark[len] = 0; // 这个是关键啊 41 len--; 42 } 43 } 44 printf("%.7lf ", (double)sum/len); 45 } 46 } 47 return 0; 48 }
ps:学完树状数组后会补上运用树状数组解决的方法