数据结构总结之线段树

来源:互联网 发布:燕十八php教程 网盘 编辑:程序博客网 时间:2024/06/05 15:04

1.线段树模板,先建树后,可实现查找,更新
poj2528

#include <iostream>#include <stdio.h>using namespace std;#define N 111111long long sum[N<<2];//数组开的太大,要用宏定义,不然RElong long add[N<<2];void pushdown(int m,int rt){    if(add[rt])    {        add[rt*2]+=add[rt];        add[rt*2+1]+=add[rt];        sum[rt*2]+=add[rt]*(m-(m/2));        sum[rt*2+1]+=add[rt]*(m/2);        add[rt]=0;    }}void build(int l,int r,int rt){    add[rt]=0;    if(l==r)    {        scanf("%I64d",&sum[rt]);        return ;    }    int mid=(r+l)/2;    build(l,mid,rt*2);    build(mid+1,r,rt*2+1);    sum[rt]=sum[rt*2]+sum[rt*2+1];}void update(int l,int r,int rt,int L,int R,int c){    if(l<=L && r>=R)    {        sum[rt]+=(long long)c*(R-L+1);        add[rt]+=c;        return ;    }    pushdown(R-L+1,rt);    int mid=(R+L)/2;    if(l<=mid) update(l,r,rt*2,L,mid,c);    if(r>mid) update(l,r,rt*2+1,mid+1,R,c);    sum[rt]=sum[rt*2]+sum[rt*2+1];}long long query(int l,int r,int rt,int L,int R){    long long ans=0;    if(l<=L && r>=R) return sum[rt];    pushdown(R-L+1,rt);    int mid=(R+L)/2;    if(l<=mid) ans+=query(l,r,rt*2,L,mid);    if(r>mid) ans+=query(l,r,rt*2+1,mid+1,R);    return ans;}int main(){    int n,m;scanf("%d%d",&n,&m);    build(1,n,1);    while(m--)    {        char ch[5];scanf(" %s",ch);        int c,x,y;        if(ch[0]=='Q')        {            scanf("%d%d",&x,&y);            printf("%I64d\n",query(x,y,1,1,n));        }        else        {            scanf("%d%d%d",&x,&y,&c);            update(x,y,1,1,n,c);        }    }    return 0;}

2.边更新,边查找:poj2352

#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int maxn=32010;int tree[4*maxn];int x[maxn];int level[15010];void build(int p,int l,int r,int x){    if(l==r) {tree[p]++;return ;}    int mid=(l+r)/2;    if(x>mid) build(2*p+1,mid+1,r,x);    else build(2*p,l,mid,x);    tree[p]=tree[2*p+1]+tree[2*p];}int find_(int p,int l,int r,int x,int y){    if(l==x&&r==y) return tree[p];    int mid=(l+r)/2;    if(mid>=y) return find_(2*p,l,mid,x,y);    else if(mid<=x) return find_(2*p+1,mid,r,x,y);    else return find_(2*p,l,mid,x,mid)+find_(2*p+1,mid+1,r,mid+1,y);}int main(){    int n;cin>>n;    int max_x=-1;    for(int i=0;i<n;i++)    {        int y;        scanf("%d%d",&x[i],&y);        if(max_x<x[i]) max_x=x[i];    }    for(int i=0;i<n;i++)    {        build(1,0,max_x,x[i]);        level[find_(1,0,max_x,0,x[i])-1]++;    }    for(int i=0;i<n;i++)        printf("%d\n",level[i]);    return 0;}

3.区间太大的话,可以用离散化处理:poj2528
4.查询区间再大的话,就用离线算法:hdu4417

原创粉丝点击