pku2155 Matrix

这题的要求和树状数组的使用方法恰好相反,改变的是一个区间,查询的反而是一个点。我们先看一维的情况。

首先定义

Up(a)={a1=a,a2=a1+lowbit(a1),a3=a2+lowbit(a2) ... }

Down(a)={a1=a,a2=a1-lowbit(a1),a3=a2-lowbit(a2) ... }

为了方便讨论,只说明初始化后的第一次“C a b”和“Q c”操作:

对于命令“C a b”,我们分别调用函数down(b,1)和down(a-1,-1),将下标属于集合Down(b)的C中的元素+1,下标属于集合Down(a-1)的C中的元素-1,联系到通常树状数组的求和为down(b)-down(a-1),这里只不过把取值操作转变为对值的修改;

然后分情况讨论函数up(c)如何对点进行查询,可以发现对于任意的a<=b,Up(a)与Down(b)的交集只有一个元素。

因此

当a<c<=b时,Up(c)与Down(a-1)无交集,与Down(b)有交集且交集内只有一个元素,由之前的修改可知该元素为1,故返回1;

当b<c时,Up(c)与Down(b)无交集,故返回0;

当c<=a时,Up(c)分别与Down(b)和Down(a-1)构成一个元素的交集,其元素分别为-1和1,抵消后返回0;

此时返回值就是点c处的值。

了解如何获得第一次修改后的询问结果后,只要将简单的返回值变更为对下标属于集合Up(c)的C中元素的累加值,就能得到多次修改后的询问结果,然后扩展至二维即可

 

 

/*

Source Code

Problem: 2155  User: zgmf_x20a 
Memory: 4160K  Time: 438MS 
Language: C++  Result: Accepted 

*/

#include 
<iostream>
#include 
<algorithm>
using namespace std;

#define MAXN 1005
#define clr(x) memset(x,0,sizeof(x))

int c[MAXN][MAXN],n,query;

inline 
int lowbit(int x){
    
return x&(-x);
}

void down(int x,int y,int tt){
    
int i=x,j=y;
    
while(i>0){
        j
=y;
        
while(j>0){
            c[i][j]
+=tt;
            j
-=lowbit(j);
        }
        i
-=lowbit(i);
    }
}

int up(int x,int y){
    
int i=x,j=y,res=0;
    
while(i<=n){
        j
=y;
        
while(j<=n){
            res
+=c[i][j];
            j
+=lowbit(j);
        }
        i
+=lowbit(i);
    }
    
return res;
}

int main(){
    
int T,x1,y1,x2,y2;
    
char str[3];
    scanf(
"%d",&T);
    
while(T--){
        clr(c);
        scanf(
"%d%d",&n,&query);
        
while(query--){
            scanf(
"%s",str);
            
if(str[0]=='C'){
                scanf(
"%d%d%d%d",&x1,&y1,&x2,&y2);
                down(x2,y2,
1);
                down(x1
-1,y2,-1);
                down(x2,y1
-1,-1);
                down(x1
-1,y1-1,1);
            }
            
else{
                scanf(
"%d%d",&x1,&y1);
                printf(
"%d\n",up(x1,y1)%2);
            }
        }
        printf(
"\n");
    }
    
return 0;
}

 

 

另附二维线段树代码

 

/*

Source Code

Problem: 2155  User: zgmf_x20a 
Memory: 56440K  Time: 1922MS 
Language: C++  Result: Accepted
 
*/


#include 
<iostream>
using namespace std;

#define MAXN 1001
#define clr(x) memset(x,0,sizeof(x))

int n,m;

struct Node{
    
int l,r,cnt;
};

class SegTree{
    Node nod[
3*MAXN];
public:
    
void BuildTree(int u,int l,int r){
        nod[u].l
=l;
        nod[u].r
=r;
        nod[u].cnt
=0;
        
if(l==r)
            
return;
        BuildTree(
2*u,l,(l+r)/2);
        BuildTree(
2*u+1,(l+r)/2+1,r);
    }
    
void Insert(int u,int l,int r){
        
if(l<=nod[u].l && nod[u].r<=r){
            nod[u].cnt
++;
            
return;
        }
        
if(l<=nod[2*u].r)
            Insert(
2*u,l,r);
        
if(r>=nod[2*u+1].l)
            Insert(
2*u+1,l,r);

    }
    
int Query(int u,int l,int r,int sum){
        sum
+=nod[u].cnt;
        
if(l<=nod[u].l && nod[u].r<=r)
            
return sum;
        
int res=0;
        
if(l<=nod[2*u].r)
            res
+=Query(2*u,l,r,sum);
        
if(r>=nod[2*u+1].l)
            res
+=Query(2*u+1,l,r,sum);
        
return res;
    }
};

struct _2DNode{
    SegTree tre;
    
//二维线段树中每个区间被翻转的次数用一维线段树统计
    int l,r;
};

class _2DSegTree{
    _2DNode _2Dnod[
3*MAXN];
public:
    
void _2DBuildTree(int u,int xl,int xr,int yl,int yr){
        _2Dnod[u].l
=xl;
        _2Dnod[u].r
=xr;
        _2Dnod[u].tre.BuildTree(
1,yl,yr);
        
if(xl==xr)
            
return;
        _2DBuildTree(
2*u,xl,(xl+xr)/2,yl,yr);
        _2DBuildTree(
2*u+1,(xl+xr)/2+1,xr,yl,yr);
    }
    
void _2DInsert(int u,int xl,int xr,int yl,int yr){
        
if(xl<=_2Dnod[u].l && _2Dnod[u].r<=xr){
            _2Dnod[u].tre.Insert(
1,yl,yr);
            
return;
        }
        
if(xl<=_2Dnod[2*u].r)
            _2DInsert(
2*u,xl,xr,yl,yr);
        
if(xr>=_2Dnod[2*u+1].l)
            _2DInsert(
2*u+1,xl,xr,yl,yr);
    }
    
int _2DQuery(int u,int xl,int xr,int yl,int yr,int sum){
        sum
+=_2Dnod[u].tre.Query(1,yl,yr,0);
        
if(xl<=_2Dnod[u].l && _2Dnod[u].r<=xr)
            
return sum;
        
int res=0;
        
if(xl<=_2Dnod[2*u].r)
            res
+=_2DQuery(2*u,xl,xr,yl,yr,sum);
        
if(xr>=_2Dnod[2*u+1].l)
            res
+=_2DQuery(2*u+1,xl,xr,yl,yr,sum);
        
return res;
    }
};


_2DSegTree tr;


int main(){
    
int i,T,xl,xr,yl,yr;
    
char str[3];
    scanf(
"%d",&T);
    
while(T--){
        scanf(
"%d%d",&n,&m);
        tr._2DBuildTree(
1,1,n,1,n);
        
for(i=0;i<m;i++){
            scanf(
"%s",str);
            
if(str[0]=='C'){
                scanf(
"%d%d%d%d",&xl,&yl,&xr,&yr);
                tr._2DInsert(
1,xl,xr,yl,yr);
            }
            
else{
                scanf(
"%d%d",&xl,&yl);
                printf(
"%d\n",tr._2DQuery(1,xl,xl,yl,yl,0)%2);
            }
        }
        printf(
"\n");
    }
    
return 0;
}
posted @ 2008-10-29 23:33  Beetlebum  阅读(452)  评论(0编辑  收藏  举报