树状数组与普通线段树模板

树状数组(区间修改,单点求值)

 1 const int N=500005;
 2 int a[N],c[N],n,m;
 3 
 4 void modify(int x,int y)
 5 {
 6     for(;x<=n;x+=x&(-x)) c[x]+=y;
 7 }
 8 
 9 int query(int x)
10 {
11     int res=0;
12     for(;x;x-=x&(-x)) res+=c[x];
13     return res;
14 }
15 
16 int main()
17 {
18     scanf("%d%d",&n,&m);
19     FOR(i,1,n) scanf("%d",&a[i]);
20     while(m--)
21     {
22         int opt;scanf("%d",&opt);
23         if(opt==1)
24         {
25             int x,y,k;
26             scanf("%d%d%d",&x,&y,&k);
27             modify(x,k);
28             modify(y+1,-k);
29         }
30         else
31         {
32             int x;scanf("%d",&x);
33             printf("%d\n",query(x)+a[x]);
34         }
35     }
36     return 0;
37 }

线段树(区间修改,区间求值)

const int N=100005;
struct tree
{
    int l,r;
    ll sum,add;
    #define l(x) t[x].l
    #define r(x) t[x].r
    #define sum(x) t[x].sum
    #define add(x) t[x].add
}t[N<<2];
int a[N],n,m;

void build(int p,int l,int r)
{
    l(p)=l,r(p)=r;
    if(l==r) {sum(p)=a[l];return;}
    int mid=(l+r)>>1,q=p<<1;
    build(q,l,mid),build(q|1,mid+1,r);
    sum(p)=sum(q)+sum(q|1);
}

void pushdown(int p)
{
    if(!add(p)) return;
    int q=p<<1;
    sum(q)+=add(p)*(r(q)-l(q)+1);
    sum(q|1)+=add(p)*(r(q|1)-l(q|1)+1);
    add(q)+=add(p);
    add(q|1)+=add(p);
    add(p)=0;
}

void modify(int p,int l,int r,int k)
{
    if(l<=l(p)&&r>=r(p))
    {
        sum(p)+=(ll)k*(r(p)-l(p)+1);
        add(p)+=k;
        return;
    }
    pushdown(p);
    int mid=(l(p)+r(p))>>1,q=p<<1;
    if(l<=mid) modify(q,l,r,k);
    if(r>mid) modify(q|1,l,r,k);
    sum(p)=sum(q)+sum(q|1);
}

ll query(int p,int l,int r)
{
    if(l<=l(p) && r>=r(p)) return sum(p);
    pushdown(p);
    int mid=(l(p)+r(p))>>1,q=p<<1;
    ll val=0;
    if(l<=mid) val+=query(q,l,r);
    if(r>mid) val+=query(q|1,l,r);
    return val;
}

int main()
{
    freopen("hh.out","w",stdout);
    scanf("%d%d",&n,&m);
    FOR(i,1,n) scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        int opt;scanf("%d",&opt);
        if(opt==1)
        {
            int x,y,k;
            scanf("%d%d%d",&x,&y,&k);
            modify(1,x,y,k);
        }
        else
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%lld\n",query(1,x,y));
        }
    }
    return 0;
}

 动态开点(权值线段树)

 1 struct tree
 2 {
 3     int lc,rc;
 4     int dat;
 5 }t[N<<1];
 6 int root,tot;
 7 
 8 int build()
 9 {
10     t[++tot].lc=t[tot].rc=t[tot].dat=0;
11     return tot;
12 }
13 void insert(int p,int l,int r,int val,int k)
14 {
15     if(l==r){t[p].dat+=k;return;}
16     int mid=(l+r)>>1;
17     if(val<=mid)
18     {
19         if(!t[p].lc) t[p].lc=build();
20         insert(t[p].lc,l,mid,val,k);
21     }
22     else
23     {
24         if(!t[p].rc) t[p].rc=build();
25         insert(t[p].rc,mid+1,r,val,k);
26     }
27     t[p].dat=t[t[p].lc].dat+t[t[p].rc].val;
28 }
29 
30 int main()
31 {
32     root=build();
33     insert(root,1,n,val,k);
34 }

线段树合并(相同权值)

 1 int merge(int p,int q,int l,int r)
 2 {
 3     if(!p) return q;
 4     if(!q) return p;
 5     if(l==r) {t[p].dat+=t[q].dat;return p;}
 6     int mid=(l+r)>>1;
 7     t[p].lc=merge(t[p].lc,t[q].lc,l,mid);
 8     t[p].rc=merge(t[p].rc,t[q].rc,mid+1,r);
 9     t[p].dat=t[t[p].lc].dat+t[t[p].rc].dat;
10     return p;
11 }

 

posted @ 2019-03-15 20:57  universeplayer  阅读(183)  评论(0编辑  收藏  举报