二维线段树

#include <bits/stdc++.h>
using namespace std;
const int maxn=1010;
int n,m,ans,tree[maxn<<2][maxn<<2];
void update_y(int q1,int q2,int yl,int yr,int xt,int yt){//传入Y维要更新区间Q1,Q2,搜索区间1~N,当前X维结点,Y维初始结点1
    if(q1<=yl&&yr<=q2){//更新区间包括了当前搜索空间就直接更新
        tree[xt][yt]++;//该值累加,如果每次操作加的值会变就要再传一个VAL值
        return ;
    }
    int ymid=(yl+yr)>>1;//如果当前区间不合适,继续二分
    if(q1<=ymid)update_y(q1,q2,yl,ymid,xt,yt<<1);//要更新区间在MID左边有值就更新左儿子
    if(q2>ymid)update_y(q1,q2,ymid+1,yr,xt,yt<<1|1);//要更新区间在MID右边有值就更新右儿子
}
void update_x(int p1,int q1,int p2,int q2,int xl,int xr,int xt){//传入参数:两点坐标,当前X维搜索到的区间,当前结点
    if(p1<=xl&&xr<=p2){//两点坐标X维包括了当前搜索空间就往进入Y维更新
        update_y(q1,q2,1,n,xt,1);//传入Y维要更新区间Q1,Q2,搜索区间1~N,当前X维结点,Y维初始结点1
        return ;
    }
    int xmid=(xl+xr)>>1;//如果当前区间不合适,继续二分
    if(p1<=xmid)update_x(p1,q1,p2,q2,xl,xmid,xt<<1);//要更新区间在MID左边有值就更新左儿子
    if(p2>xmid)update_x(p1,q1,p2,q2,xmid+1,xr,xt<<1|1);//要更新区间在MID右边有值就更新右儿子
}
void query_y(int y,int yl,int yr,int xt,int yt){//传参:查询Y坐标,Y维区间,X维结点编号,Y维结点编号
    ans=ans+tree[xt][yt];//将每个值都加上防止遗漏
    if(yl==yr) return ;//叶子结点跳出
    int ymid=(yl+yr)>>1;//二分
    if(y<=ymid)query_y(y,yl,ymid,xt,yt<<1);//要查询区间在MID左边有值就查询左儿子
    if(y>ymid)query_y(y,ymid+1,yr,xt,yt<<1|1);//要更新区间在MID右边有值就更新右儿子
}
void query_x(int x,int y,int xl,int xr,int xt){//传参:查询坐标,X维区间,结点编号
    query_y(y,1,n,xt,1);//传参:查询Y坐标,Y维区间,X维结点编号,Y维结点编号
    if(xl==xr) return ;//叶子结点跳出
    int xmid=(xl+xr)>>1;//二分
    if(x<=xmid)query_x(x,y,xl,xmid,xt<<1);//要查询区间在MID左边有值就查询左儿子
    if(x>xmid)query_x(x,y,xmid+1,xr,xt<<1|1);//要更新区间在MID右边有值就更新右儿子
}
int main(){
    int QAQ;scanf("%d",&QAQ);//QAQ个样例
    while(QAQ--){
        memset(tree,0,sizeof(tree));//记得初始化
        scanf("%d%d",&n,&m);//输入行列数,操作数
        char q;int p1,q1,p2,q2;
        for(int i=0;i<m;i++){
            scanf(" %c",&q);
            if(q=='C'){
                scanf("%d%d%d%d",&p1,&q1,&p2,&q2);
                update_x(p1,q1,p2,q2,1,n,1);//传参:两点坐标,区间,结点编号
            }//对区间操作全更新1,X维开始
            if(q=='Q'){
                scanf("%d%d",&p1,&q1);
                ans=0;
                query_x(p1,q1,1,n,1);//传参:坐标,区间,结点编号
                printf("%d\n",ans%2);
            }//对区间操作全更新1,X维开始
        }
        printf("\n");
    }
}
POJ-2155:Matrix
二维线段树:给你一个二维表格,执行两种操作,第一种给你左上角和右下角的坐标,让你把这个矩形内的数翻转,即0变成1,1变成0。第二种操作就是查询某个点当前的值
Sample Input
1
2 10
C 2 1 2 2
Q 2 2
C 2 1 2 1
Q 1 1
C 1 1 2 1
C 1 2 1 2
C 1 1 2 2
Q 1 1
C 1 1 2 1
Q 2 1
Sample Output
1
0
0
1

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值