线段树(区间修改,单点查询)

题目链接:https://vjudge.net/contest/196267#problem/B

题号:zoj-3284

题目大意:就是给你一个矩阵,让你实现一些修改和查询操作

题目思路:建立两个线段树,不细说


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i>1;
     build(t,L,mid,pos<<1);
     build(t,mid+1,R,pos<<1|1);
}
void updown(node *t,int pos)//更新延迟标记,就是相当于分块里面标记整个块,这里标记的是整个区间
{
    if(t[pos].add!=0)
    {
        t[pos<<1].add+=t[pos].add;
        t[pos<<1|1].add+=t[pos].add;
        t[pos<<1].sum+=(t[pos<<1].r-t[pos<<1].l+1)*t[pos].add;
        t[pos<<1|1].sum+=(t[pos<<1|1].r-t[pos<<1|1].l+1)*t[pos].add;
        t[pos].add=0;
    }
}
void upup(node *t,int pos)//回溯求和
{
    t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
int query(node *t,int x,int pos)//单点查询,查询第x个元素的值
{
    if(t[pos].l==t[pos].r)
    {
        return t[pos].sum;
    }
    int mid=(t[pos].l+t[pos].r)>>1;
    updown(t,pos);
    if(x<=mid)
        return query(t,x,pos<<1);
    //if(R>mid)
    else
        return query(t,x,pos<<1|1);
}
void updata(node *t,int L,int R,int ad,int pos)//区间修改,L-R区间的所有元素加上ad
{
    if(L<=t[pos].l&&t[pos].r<=R)
    {
        t[pos].sum+=(t[pos].r-t[pos].l+1)*ad;
        t[pos].add+=ad;
        return ;
    }
    int mid=(t[pos].l+t[pos].r)>>1;
    updown(t,pos);
    if(L<=mid)
    updata(t,L,R,ad,pos<<1);//这里需要注意一下,容易写错
    if(R>mid)
    updata(t,L,R,ad,pos<<1|1);//这里需要注意一下,容易写错
    upup(t,pos);
}
int main()
{
    int n,m;
    int kases=0;
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=0;i<(10010<<2);i++)
        {
            p[i].sum=0;p[i].add=0;
            q[i].add=0;q[i].sum=0;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
        build(p,1,n*m,1);
        build(q,1,n*m,1);
        int t;
        scanf("%d",&t);
        printf("Case %d\n",++kases);
        for(int i=1;i<=t;i++)
        {
            int x;
            scanf("%d",&x);
            if(x==0)
            {
                int r1,c1,r2,c2,ad;
                scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&ad);
                int l=(r1-1)*m+c1,r=(r2-1)*m+c2;
                updata(p,l,r,ad,1);
            }
            else if(x==1)
            {
                int r1,c1,r2,c2,ad;
                scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&ad);
                int l=(c1-1)*n+r1,r=(c2-1)*n+r2;
                updata(q,l,r,ad,1);
            }
            else if(x==2)
            {
                int r,c;
                scanf("%d%d",&r,&c);
                int ans=query(p,(r-1)*m+c,1)+query(q,(c-1)*n+r,1)+a[r][c];
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


补充:

区间修改区间求求和:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ri(n) scanf("%d",&n)
#define oi(n) printf("%d\n",n)
#define rl(n) scanf("%lld",&n)
#define ol(n) printf("%lld\n",n)
#define rep(i,l,r) for(i=l;i<=r;i++)
#define rep1(i,l,r) for(i=l;i>1;
    //int mid=(l+r)>>1;
    build(t,l,mid,pos<<1);
    build(t,mid+1,r,pos<<1|1);
    t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
void pushdown(node *t,int pos)
{
    if(t[pos].add!=0)
    {
        t[pos<<1].add+=t[pos].add;
        t[pos<<1].sum+=(t[pos<<1].r-t[pos<<1].l+1)*t[pos].add;
        t[pos<<1|1].add+=t[pos].add;
        t[pos<<1|1].sum+=(t[pos<<1|1].r-t[pos<<1|1].l+1)*t[pos].add;
        t[pos].add=0;
    }
}
ll query(node *t,int l,int r,int pos)
{
    if(l<=t[pos].l&&t[pos].r<=r)
    {
        return t[pos].sum;
    }
    ll ans=0;
    int mid=(t[pos].l+t[pos].r)>>1;
    pushdown(t,pos);
    if(l<=mid)
        ans+=query(t,l,r,pos<<1);
    if(r>mid)
        ans+=query(t,l,r,pos<<1|1);
    return ans;
}
void updata(node *t,int l,int r,int ad,int pos)
{
    if(l<=t[pos].l&&t[pos].r<=r)//这里一定要注意是<=和>=
    {
        t[pos].sum+=(t[pos].r-t[pos].l+1)*ad;
        t[pos].add+=ad;
        return ;
    }
    int mid=(t[pos].l+t[pos].r)>>1;
    pushdown(t,pos);
    if(l<=mid)
        updata(t,l,r,ad,pos<<1);//这里是l,r,不是l,mid
    if(r>mid)
        updata(t,l,r,ad,pos<<1|1);//这里是l,r,不是mid+1,r
    t[pos].sum=t[pos<<1].sum+t[pos<<1|1].sum;
}
int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    build(tr,1,n,1);
    for(int i=1;i<=q;i++)
    {
        char c;
        //scanf("%c",&c);
        cin>>c;
        if(c=='Q')
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(tr,l,r,1));
        }
        else
        {
            int l,r,ad;
            scanf("%d%d%d",&l,&r,&ad);
            updata(tr,l,r,ad,1);
        }
    }
    return 0;
}



你可能感兴趣的:(线段树,数据结构)