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

来源:互联网 发布:java 异或运算符 编辑:程序博客网 时间:2024/05/17 04:27

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

题号:zoj-3284

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

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


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#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<r;i++)using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int epg=10-8;struct node{    int l,r;    int sum,add;}p[10010<<2],q[10010<<2];int a[110][110];void build(node *t,int L,int R,int pos)//建立线段树{     t[pos].l=L;     t[pos].r=R;     t[pos].sum=0;     t[pos].add=0;     if(L==R)     {         return ;     }     int mid=(L+R)>>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 <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#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<r;i++)using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int epg=10-8;struct node{    int l,r;    ll add,sum;}tr[100010<<2];ll a[100010<<2];void build(node *t,int l,int r,int pos){    t[pos].l=l;    t[pos].r=r;    t[pos].add=0;    if(l==r)    {        t[pos].sum=a[l];        return;    }    int mid=(t[pos].l+t[pos].r)>>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;}



阅读全文
0 0
原创粉丝点击