线段树
线段树:http://blog.csdn.net/shiqi_614/article/details/8228102(帖子总结的很好,可以参考题目)
http://blog.csdn.net/metalseed/article/details/8039326
特性:平衡二叉树,查询和插入都是log(n)
线段树:
1)单点更新
2)区间更新,用延迟标记,避免区间左右儿子进行更新操作;只有当query时才需要进行更新;
3)区间合并
线段树的类:实现区间增加一个值,并延迟更新
- #define LL(x) (x<<1)
- #define RR(x) (x<<1|1)
- #define MID(a,b) (a+((b-a)>>1))
- const int N=100005;
- typedef long long LL;
- struct node
- {
- int lft,rht;
- LL sum,add;
- int mid(){return MID(lft,rht);}
- void fun(LL tmp)
- {
- add+=tmp;
- sum+=(rht-lft+1)*tmp;
- }
- };
- int y[N];
- struct Segtree
- {
- node tree[N*4];
- void relax(int ind)
- {
- if(tree[ind].add)
- {
- tree[LL(ind)].fun(tree[ind].add);
- tree[RR(ind)].fun(tree[ind].add);
- tree[ind].add=0;
- }
- }
- void build(int lft,int rht,int ind)
- {
- tree[ind].lft=lft; tree[ind].rht=rht;
- tree[ind].sum=0; tree[ind].add=0;
- if(lft==rht) tree[ind].sum=y[lft];
- else
- {
- int mid=tree[ind].mid();
- build(lft,mid,LL(ind));
- build(mid+1,rht,RR(ind));
- tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
- }
- }
- void updata(int st,int ed,int ind,int add)
- {
- int lft=tree[ind].lft,rht=tree[ind].rht;
- if(st<=lft&&rht<=ed) tree[ind].fun(add);
- else
- {
- relax(ind);
- int mid=tree[ind].mid();
- if(st<=mid) updata(st,ed,LL(ind),add);
- if(ed> mid) updata(st,ed,RR(ind),add);
- tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum;
- }
- }
- LL query(int st,int ed,int ind)
- {
- int lft=tree[ind].lft,rht=tree[ind].rht;
- if(st<=lft&&rht<=ed) return tree[ind].sum;
- else
- {
- relax(ind);
- int mid=tree[ind].mid();
- LL sum1=0,sum2=0;
- if(st<=mid) sum1=query(st,ed,LL(ind));
- if(ed> mid) sum2=query(st,ed,RR(ind));
- return sum1+sum2;
- }
- }
- }seg;
基本实现:主要实现单点更新
- #include<iostream>
- using namespace std;
- struct TreeNode{
- int start;
- int end;
- int cnt;
- TreeNode *left;
- TreeNode *right;
- TreeNode(int start,int end):start(start),end(end){
- left = NULL;
- right = NULL;
- cnt=0;
- }
- };
- void update(TreeNode *root, int i,int cnt,bool flag) {
- if(root==NULL) return;
- if(root->start <= i && i<=root->end) {
- if(flag == true) root->cnt += cnt;
- else root->cnt -= cnt;
- int mid = root->start + (root->end - root->start)/2;
- if(i>mid) update(root->right,i,cnt,flag);
- else update(root->left,i,cnt,flag);
- }
- }
- int query(TreeNode *root,int i,int j) {
- if(root==NULL) return 0;
- if(i>j) return 0;
- int start = root->start;
- int end = root->end;
- int mid = start + (end-start)/2;
- if(start==i && j==end) return root->cnt;
- if(j<=mid) return query(root->left,i,j);
- else if(i<=mid) return query(root->left,i,mid) + query(root->right,mid+1,j);
- else return query(root->right,i,j);
- }
- TreeNode * addSegTree(int start,int end) {
- TreeNode * root = new TreeNode(start,end);
- if(start!=end) {
- int mid = start + (end-start)/2;
- root->left = addSegTree(start,mid);
- root->right = addSegTree(mid+1,end);
- }
- return root;
- }
- void preorder(TreeNode *root) {
- if(root==NULL) return;
- cout<<"["<<root->start<<","<<root->end<<"]"<<endl;
- preorder(root->left);
- preorder(root->right);
- }
- int main(){
- int start=1;
- int end=10;
- // cin>>start>>end;
- TreeNode *root = addSegTree(start,end);
- for(int i=1;i<=10;i++)
- update(root,i,i,true);
- cout<<query(root,1,3)<<endl;
- update(root,3,6,true);
- cout<<query(root,2,7)<<endl;
- update(root,10,2,false);
- update(root,6,3,true);
- cout<<query(root,3,10)<<endl;
- // preorder(root);
- return 0;
- }