#include <cstdio> #include <iostream> #include <cstring> using namespace std; typedef long long LL; const int maxn=1e5+7; int a[maxn],tree[maxn*4]; int lz[maxn*4]; void build(int node ,int start, int endd) { if(start == endd)//叶子节点 { tree[node] = a[start]; return ; } else{ int mid = start + ((endd - start) >> 1); int lson = node << 1 ;//左儿子:2 * node int rson = (node << 1) | 1;//右儿子:2 * node + 1 build(lson, start, mid); build(rson, mid+1, endd); tree[node] = tree[lson] + tree[rson]; } } //单点更新,idx为需要更新的叶子节点编号,add为更改值 void update(int node, int start, int endd, int idx, int instead) { if(start == endd) { tree[start] = instead; return ; } else { int mid = start + (endd - start) >> 1; int lson = (node << 1); int rson = (node << 1) | 1; if( idx <= mid) { update(lson, start, mid, idx, instead); } else { update(rson, mid+1, endd, idx, instead); } tree[node] = tree[lson] + tree[rson]; } } //单点查询 LL query(LL node,LL l,LL r,LL x) { if(l==r&&l==x) return tree[num]; LL mid=(l+r)>>1,tmp; if(x<=mid) tmp=query(num*2,l,mid,x); else tmp=query(num*2+1,mid+1,r,x); return tmp+tree[num]; } LL query(int node, int start, int endd, int l, int r) { LL sum=0; if(l>endd || r<start) { return 0; } if(l<=start && r>=endd) { return tree[node]; } int mid = start + (endd - start) >> 1; int lson = node << 1; int rson = (node << 1) | 1; LL sum_left = query(lson, start, mid, l, r); LL sum_right = query(rson, mid+1, endd, l, r); sum = sum_left + sum_right; return sum; } ------------------------------------------------------------------------------ //区间加值 void push_up(int node) { tree[node] = tree[node<<1] + tree[(node<<1)|1]; } void push_down(int node, int l, int r) { int lson = (node << 1); int rson = (node << 1) | 1; if(lz[node]) { lz[lson] = lz[node]; lz[rson] = lz[node]; int mid = l + (r - l) >> 1; tree[lson] += lz[node] * (mid-l+1); tree[rson] += lz[node] * (r-mid); lz[node] = 0; //lazy标记使用完后需清零 } } void update(int node, int start, int endd, int l, int r, int add) { if(l<=start && r>=endd)//当前结点被所查询的区间覆盖 { lz[node] += add; //更新该结点所需的更新信息 tree[node] += add * (r-l+1);//更新该结点信息 return ; //lazy只需记录到当前结点 } push_down(node, start, endd); int mid = start + ((endd - start)>>1);int mid = l + ((r-l)>>1); if(l <= mid) update( node<<1, start, mid, l, r, add); if(r >= mid) update( (node<<1)|1, mid+1, endd, l, r, add); push_up(node);//向上递归时需一步一步更新回父节点 } LL query(int node, int start, int endd, int l, int r) { if(l <= start && r>=endd) { return tree[node]; } push_down(node, start, endd); int mid = start + ((endd - start)>>1); LL ans = 0; if(l <= mid) ans += query( node<<1, start, mid, l, r); if(r >= mid+1) ans += query( node<<1|1, mid+1, endd, l, r); return ans; } ------------------------------------------------------------------------------ //区间改值 void pushup(int node) { tree[node] = tree[node<<1] + tree[node<<1|1]; } void pushdown(int node, int start, int endd) { if(lz[node]) { int c = lz[node]; lz[node<<1] = c; lz[node<<1|1] = c; int mid = start + ((endd - start)>>1); tree[node<<1] = (mid-start+1) * c; tree[node<<1] = (endd-mid) * c; lz[node] = 0; } } void update(int node, int start, int endd, int l, int r,int c) { if(l <= start && r >= endd) { lz[node] = c; tree[node] = (endd-start+1) * c; return ; } pushdown(node, start, endd); int mid = start + ((endd - start)>>1); if(l <= mid) update(node<<1, start, mid, l, r, c); if(r >= mid+1) update(node<<1|1, mid+1, endd, l, r,c); pushup(node); } LL query(int node, int start, int endd, int l, int r) { if(l <= start && r >= endd) { return tree[node]; } pushdown(node, start, endd); int mid = start + ((endd-start)>>1); LL ans=0; if(l <= mid) ans+=query(node<<1, start, mid, l, r); if(r >= mid+1) ans+=query(node<<1|1, mid+1, endd, l, r); return ans; } int main() { int q=1; for(int i=1;i<=6;i++) { a[i]=q++; } build(1,1,6); for(int i=1;i<=15;i++) { printf("tree[%d]:%d ",i,tree[i]); } return 0; } -------------------------------------------------------------------------------------- //求区间最大值 void update(int o,int l,int r,int ind,int ans){ //o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值; if(l==r){ //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回 st[o]=ans; return; } int m=l+((r-l)>>1); if(ind<=m){ //若需要更新的叶子结点在当前结点的左儿子结点的范围内,则递归更新左儿子结点,否则更新右儿子结点 update(o<<1,l,m,ind,ans); } else{ update((o<<1)|1,m+1,r,ind,ans); } st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值) } { //在main函数中的语句 update(1,1,n,ind,ans); } int query(int o,int l,int r,int ql,int qr){ //ql、qr为需要查询的区间左右端点 if(ql>r||qr<l) return -1; //若当前结点和需要查找的区间不相交,则返回一个对于区间查询无关的值(如求和时返回0,求最大值时返回-1等) if(ql<=l&&qr>=r) return st[o]; //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息 int m=l+((r-l)>>1); int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr); //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息 return max(p1,p2); //综合两个儿子结点的信息并返回 } { //main函数中的语句 printf("%d ",query(1,1,n,a,b)); }