2维线段树

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<stdlib.h>
using namespace std;
const int mod=99999997;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3fffffff;
const int mmax=510;


typedef long long LL;
struct node
{
    int l1,r1,l2,r2;
    int sum,max_val,min_val;
    int mid1()
    {
        return (l1+r1)>>1;
    }
    int mid2()
    {
        return (l2+r2)>>1;
    }
}T[4*mmax][4*mmax];

int a[mmax][mmax];
void push_up1D(int id1,int id2)
{
    T[id1][id2].l2=T[id1<<1][id2].l2,T[id1][id2].r2=T[id1<<1][id2].r2;
    T[id1][id2].sum=T[id1<<1][id2].sum+T[id1<<1|1][id2].sum;
    T[id1][id2].max_val=max(T[id1<<1][id2].max_val,T[id1<<1|1][id2].max_val);
    T[id1][id2].min_val=min(T[id1<<1][id2].min_val,T[id1<<1|1][id2].min_val);
    if(T[id1][id2].l2==T[id1][id2].r2)
        return ;
    push_up1D(id1,id2<<1);
    push_up1D(id1,id2<<1|1);

}
void push_up2D(node &T,node &Tl,node &Tr)
{
    T.sum=Tl.sum+Tr.sum;
    T.max_val=max(Tl.max_val,Tr.max_val);
    T.min_val=min(Tl.min_val,Tr.min_val);
}

void build2D(int id1,int id,int l,int r)
{
    T[id1][id].l2=l,T[id1][id].r2=r;
    if(l==r)
    {
        T[id1][id].sum=T[id1][id].max_val=T[id1][id].min_val=a[T[id1][1].l1][l];
        return ;
    }
    int mid=T[id1][id].mid2();
    build2D(id1,id<<1,l,mid);
    build2D(id1,id<<1|1,mid+1,r);
    push_up2D(T[id1][id],T[id1][id<<1],T[id1][id<<1|1]);
}
void build1D(int id,int l,int r,int m)
{
    T[id][1].l1=l,T[id][1].r1=r;
    if(l==r)
    {
        build2D(id,1,1,m);
        return ;
    }
    int mid=T[id][1].mid1();
    build1D(id<<1,l,mid,m);
    build1D(id<<1|1,mid+1,r,m);
    push_up1D(id,1);
}
node query2D(int id1,int id,int l,int r)
{
    if(l<=T[id1][id].l2&&T[id1][id].r2<=r)
        return T[id1][id];
    int mid=T[id1][id].mid2();
    //cout<<T[id1][id].l2<<" "<<T[id1][id].r2<<endl;
    node tmp[3];
    int t=0;
    if(mid>=l)
        tmp[1]=query2D(id1,id<<1,l,r),t++;
    if(mid<r)
        tmp[2]=query2D(id1,id<<1|1,l,r),t+=2;
    if(t<3)
        return tmp[t];
    push_up2D(tmp[0],tmp[1],tmp[2]);
    return tmp[0];
}
node query1D(int id,int l1,int r1,int l2,int r2)
{
    if(l1<=T[id][1].l1&&T[id][1].r1<=r1)
        return query2D(id,1,l2,r2);
    int mid=T[id][1].mid1();
    node tmp[3];
    int t=0;
    if(mid>=l1)
        tmp[1]=query1D(id<<1,l1,r1,l2,r2),t++;
    if(mid<r1)
        tmp[2]=query1D(id<<1|1,l1,r1,l2,r2),t+=2;
    if(t<3)
        return tmp[t];
    push_up2D(tmp[0],tmp[1],tmp[2]);
    return tmp[0];
}
void updata2D(int id1,int id,int pos,int val)
{
    if(T[id1][id].l2==T[id1][id].r2)
    {
        T[id1][id].sum=T[id1][id].max_val=T[id1][id].min_val=val;
        return ;
    }
    int mid=T[id1][id].mid2();
    if(mid>=pos)
        updata2D(id1,id<<1,pos,val);
    else
        updata2D(id1,id<<1|1,pos,val);
    push_up2D(T[id1][id],T[id1][id<<1],T[id1][id<<1|1]);
}
void updata1D(int id,int posx,int posy,int val)
{
    if(T[id][1].l1==T[id][1].r1)
    {
        updata2D(id,1,posy,val);
        return ;
    }
    int mid=T[id][1].mid1();
    if(mid>=posx)
        updata1D(id<<1,posx,posy,val);
    else
        updata1D(id<<1|1,posx,posy,val);
    push_up1D(id,1);
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,m,q;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    build1D(1,1,n,m);
    cin>>q;
    while(q--)
    {
        int X1,X2,Y1,Y2;
        char ch[2];
        scanf("%s",ch);
        if(ch[0]=='q')
        {
            scanf("%d %d %d %d",&X1,&Y1,&X2,&Y2);
            node ans=query1D(1,X1,X2,Y1,Y2);
            printf("%d %d\n",ans.max_val,ans.min_val);
        }
        if(ch[0]=='c')
        {
            int V;
            scanf("%d %d %d",&X1,&Y1,&V);
            updata1D(1,X1,Y1,V);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值