Codeforces Sereja and Array
http://codeforces.com/problemset/problem/315/B
数据结构?
这题比赛时想到了线段树,后来发现错了,确定是数据结构方向的,一直想,想了可能有20分钟的样子,觉得可以水过去,然后就去水,然后过了,赛后这题被归为数据结构,但是觉得这个分类有时候真的不太靠谱,不知道数据结构到底怎么写,但是看别人的代码,水过去的做法更多
题意:3个种操作
1 x val ,把数组下标x的元素的值改为val
2 val , 把整个数组每个元素的值都增加val
3 x , 查询下标x的元素当前的值
问题的关键是修改某个单元的值,试想2操作做了好几次,即整个数组的值加了好几个值,这时候执行1操作修改某个单元的值,那么之前2操作累加上来的值对它就没影响了,但是查询其他单元的时候是要考虑之前2操作累加上来的值
我的做法是,用一个数组来保存来每次2操作后的累加情况。如果对某个单元执行了1操作,那么记录下当时是进行到哪一次2操作,下去查询的时候,看看当时已经到了哪个2操作,用当时2操作累加的值减去上一次2操作累加的值,就是应该得到的累加值
说得有点乱,看代码更好懂,注意看delta数组,pre数组
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define N 100010 typedef long long ll; struct Delta { ll sum,val; }del[N]; ll time,n,m,a[N]; int pre[N]; int main() { // freopen("B_output.txt","w",stdout); //scanf("%d%d",&n,&m); cin >> n >> m; for(int i=1; i<=n; i++) cin >> a[i]; memset(pre,0,sizeof(pre)); del[0].sum = 0; del[0].val = 0; while(m--) { int op,x; ll val; scanf("%d",&op); if(op == 1) { cin >> x >> val; a[x] = val; pre[x] = time; } else if(op == 2) { ++time; cin >> val; del[time].val = val; del[time].sum = del[time-1].sum + del[time].val; } else { cin >> x; int p = pre[x]; ll tmp = del[time].sum - del[p].sum; cout << a[x] + tmp << endl; } } return 0; }