树状数组板子

来源:互联网 发布:迪拜购物 知乎 编辑:程序博客网 时间:2024/05/17 04:27

感觉树状数组比线段树好用多了。。。。。
为什么要用线段树。。。。。
考场上线段树会很费时间。。。。。
我是这么觉得的
(质疑线段树的存在ing)

特别声明:以下两道题都不是板子题

真正的板子题是P1954

http://codevs.cn/problem/1954/

对!就是这道题!

就叫“线段树”

不要做以下两题

看完了板子,直接做这道题,爽翻

切记切记!

傻逼,做了这道题你就S了,呵呵呵,据说大神花333行A了,打了10种情况

开始打板子

单点修改区间查询

#include <cstdio>#define lowbit(o) (o&(-o))int tree[100001];int n;inline int gi(){int f=1,p=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')p=p*10+c-'0',c=getchar();return p*f;}inline int question(int i) {int sum=0;while(i)sum+=tree[i],i-=lowbit(i);return sum;}void add(int i,int num) {while(i<=n)tree[i]+=num,i+=lowbit(i);}int main() {    int data;    n=gi();    for(int i=1;i<=n;i++)data=gi(),add(i,data);    int m=gi();int cz,a,b;while(m--) {cz=gi();a=gi();b=gi();if(cz==1)add(a,b);else printf("%d\n",question(b)-question(a-1));}return 0;}


区间操作
以codevs.cn/problem/1082P1082线段树练习3为例
区间修改单点查询
将上面代码稍作修改即可。。。。。

/*   树状数组模版 for CodeVS1082 线段树练习3    http://blog.csdn.net/qq_21841245/article/details/43956633   codevs.cn/problem/1082P1082*/#include<cstdio>#define maxN 200000#define lb(x) (x&-x)#define Thesumans S[r]-S[l-1]+(r+1)*Sum(r,C)-l*Sum(l-1,C)+Sum(l-1,Ci)-Sum(r,Ci)typedef long long LL;LL S[maxN+1],C[maxN+1],Ci[maxN+1];/*   S为原始数组前缀和(没啥用)   C为区间[i,n]的共同增量 (用树状数组维护)    那么区间修改[l,r]直接修改C[l]和C[r+1](差分)   So   区间查询[1,r]   Sum(1,r)=S[r]+rC[1]+(r-1)C[2]+(r-2)C[3]+......+2C[r-1]+C[r]   =S[r]+sigma((m-i+1)Ci)(i=1...m)   =S[r]+(m+1)sigma(C[i])(i=1...m)-sigma(C[i]*i)(i=1...m)所以维护第二个树状数组Ci(Ci[i]=C[i]*i) */          int size;inline LL Sum(int r,LL *Ar) {LL Ans=0;while(r)Ans+=Ar[r],r-=lb(r);return Ans;}inline void Update(int r,LL Num,LL *Ar) {while(r<=size)Ar[r]+=Num,r+=lb(r);}inline int gi() {int n=0,f=1;char c=getchar();while(c>'9'||c<'0') {if(c=='-')f=-1;c=getchar();}while(c<='9'&&c>='0')n=n*10+c-'0',c=getchar();return n*f;}inline void Addall(int l,int r,int n){Update(l,n,C);Update(l,l*n,Ci);Update(r+1,-n,C);Update(r+1,-n-n*r,Ci);}inline void Outsum(int l,int r){printf("%lld\n",Thesumans);}int main() {size=gi();for(int i=1; i<=size; i++)S[i]=S[i-1]+gi();int m=gi(),dt,l,r,n;while(m--)if((dt=gi())==1)l=gi(),r=gi(),n=gi(),Addall(l,r,n);else l=gi(),r=gi(),Outsum(l,r);return 0;}

我不会告诉你我还A了线段树练习4

0 0
原创粉丝点击