HDU1166-线段树模版-敌兵布阵
2015-02-05 12:50
274 查看
这种类型是线段树,关于线段树,线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。参照这个图理解下
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。参照这个图理解下
建树: void build(int left,int right,int i) { int mid; b[i].left=left; b[i].right=right; if(left==right) { b[i].sum=a[left]; return ; } mid=(left+right)/2; build(left,mid,2*i); build(mid+1,right,2*i+1); b[i].sum=b[2*i].sum+b[2*i+1].sum; } 查找: int Query(int left, int right,int i) { int mid; if(b[i].left==left && b[i].right ==right) return b[i].sum; mid=(b[i].left+b[i].right)/2; if(right<=mid) return Query(left,right,2*i); else if (left>mid ) return Query(left,right,2*i+1); else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1); } 删除,增加: void Add(int id,int num,int i) { if(b[i].left==b[i].right) { b[i].sum=b[i].sum+num; return ; } else { b[i].sum=b[i].sum+num; if(id<=b[i*2].right) Add(id,num,2*i); else Add(id,num,2*i+1); } } 所以,有了以上函数,这道题就不会超时了啊
#include <stdio.h> #include <string.h> int a[50010]; struct node { int left,right,sum; }b[150010]; void build(int left,int right,int i) { int mid; b[i].left=left; b[i].right=right; if(left==right) { b[i].sum=a[left]; return ; } mid=(left+right)/2; build(left,mid,2*i); build(mid+1,right,2*i+1); b[i].sum=b[2*i].sum+b[2*i+1].sum; } void Add(int id,int num,int i) { if(b[i].left==b[i].right) { b[i].sum=b[i].sum+num; return ; } else { b[i].sum=b[i].sum+num; if(id<=b[i*2].right) Add(id,num,2*i); else Add(id,num,2*i+1); } } int Query(int left, int right,int i) { int mid; if(b[i].left==left && b[i].right ==right) return b[i].sum; mid=(b[i].left+b[i].right)/2; if(right<=mid) return Query(left,right,2*i); else if (left>mid ) return Query(left,right,2*i+1); else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1); } int main() { int Case; int n; char str[10]; scanf("%d",&Case); int id,num; int i; int k=1; while(Case--) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } build(1,n,1); printf("Case %d:\n",k++); while(1) { scanf("%s",str); if(strcmp(str,"End")==0) break; scanf("%d%d",&id,&num); if(strcmp(str,"Query")==0) { printf("%d\n",Query(id,num,1)); } if(strcmp(str,"Add")==0) { //scanf("%d%d",&id,&num); Add(id,num,1); } if(strcmp(str,"Sub")==0) { //scanf("%d%d",&id,&num); Add(id,-num,1); } } } return 0; }文章来源:http://www.cnblogs.com/devil-91/archive/2012/08/01/2618656.html
相关文章推荐
- hdu-1166-敌兵布阵(线段树-单点修改模版)
- HDU 1166 敌兵布阵 线段树
- HDU-1166-敌兵布阵(线段树)
- HDU 1166 敌兵布阵【简单典型的线段树问题】
- hdu 1166 敌兵布阵 (简单线段树)
- HDU-1166敌兵布阵(线段树)
- hdu1166敌兵布阵(线段树)
- HDU 1166 敌兵布阵(区间求和&(线段树|树状数组))
- HDU 1166 敌兵布阵(线段树单点更新)
- HDU-1166-敌兵布阵(线段树 插点问线)
- hdu 1166 敌兵布阵 线段树
- HDU 1166 敌兵布阵 (线段树单点更新 区间查询)
- 线段树之HDU 1166 敌兵布阵
- HDU 1166 敌兵布阵(线段树版)
- hdu 1166 敌兵布阵 (线段树 单点更新 区间求和)
- HDU-1166敌兵布阵(线段树)
- HDU 1166 敌兵布阵 zwk线段树
- hdu 1166 敌兵布阵(线段树)
- HDU_1166 敌兵布阵 【线段树】
- hdu 1166 敌兵布阵【线段树,单点增减,区间求和】