luogu3374 3368树状数组

来源:互联网 发布:c语言linuxsleep 编辑:程序博客网 时间:2024/06/05 05:51
引人入胜的3374
#include <iostream>#include <cstdio>using namespace std;int c[500005], n, m, u, v, w, k;inline int lowbit(int x){return x & -x;}void add(int pos, int num){while(pos<=n){c[pos] += num;pos += lowbit(pos);}}int sum(int pos){int temp=0;while(pos){temp += c[pos];pos -= lowbit(pos);}return temp;}int main(){cin>>n>>m;for(int i=1; i<=n; i++){scanf("%d", &k);add(i, k);}for(int i=1; i<=m; i++){scanf("%d %d %d", &w, &u, &v);if(w&1)add(u, v);elseprintf("%d\n", sum(v)-sum(u-1));}return 0;}
当然,上述模板谁都会,那么3368就非常日怪了。
先讲查分。有原数组a,差分数组b:

b[i]=a[i]-a[i-1]
这有什么用?比如:对位置从2到5的数组加2得:


事实上,把数组从pos1到pos2加上数k,只需将差分数组b[pos1]加k,b[pos2+1]减k即可
赞美差分!
#include <iostream>#include <cstdio>using namespace std;int x, lastx=0, n, m, c[1000005], u, v, w;inline int lb(int x){return x & -x;}void add(int pos, int num){while(pos<=n){c[pos] += num;pos += lb(pos);}}int sum(int pos){int re=0;while(pos){re += c[pos];pos -= lb(pos);}return re;}int main(){cin>>n>>m;for(int i=1; i<=n; i++){scanf("%d", &x);add(i, x-lastx);lastx = x;}for(int i=1; i<=m; i++){scanf("%d", &x);if(x&1){scanf("%d %d %d", &u, &v, &w);add(u, w);add(v+1, -w);}else{scanf("%d", &u);printf("%d\n", sum(u));}}return 0;}


原创粉丝点击