POJ2155 Matrix(二維線段樹)

題目大意:

有一個n*n的由零組成的矩陣,給定q個操作,C爲將x1y1爲左下角,x2y2爲右下角的矩陣取反值。Q爲輸出xy的的0,1狀態。

思路:二維線段樹(樹套樹)的建造和訪問:

# include<stdio.h>
# include<stdlib.h>
# include<string.h>
int a[4010][4010],n,m,ans;
char s[1000];
void buildy(int t,int r,int l,int k,int y1,int y2){//第二維建造
    if(r==y1 && l==y2){
        a[t][k]^=1;
        return;
    }
    if((r+l)/2>=y2)
        buildy(t,r,(r+l)/2,k*2,y1,y2);
    else
        if(y1>(r+l)/2)
            buildy(t,(r+l)/2+1,l,k*2+1,y1,y2);
        else
        {
            buildy(t,r,(r+l)/2,k*2,y1,(r+l)/2);
            buildy(t,(r+l)/2+1,l,k*2+1,(r+l)/2+1,y2);
        }
}

void buildx(int t,int r,int l,int x1, int y1, int x2, int y2){//建樹
    if(r==x1 && l==x2){
        buildy(t,1,n,1,y1,y2);
        return;
    }
    if((r+l)/2>=x2)  
        buildx(2*t,r,(r+l)/2,x1,y1,x2,y2);  
    else  
        if(x1>(r+l)/2)  
            buildx(2*t+1,(r+l)/2+1,l,x1,y1,x2,y2);  
        else  
        {  
            buildx(2*t,r,(r+l)/2,x1,y1,(r+l)/2,y2);  
            buildx(2*t+1,(r+l)/2+1,l,(l+r)/2+1,y1,x2,y2);  
        }  
}
void findy(int t,int r,int l,int k,int y){//查詢二維
    ans^=a[t][k];
    if(l==r)return;
    if((r+l)/2>=y){
        findy(t,r,(r+l)/2,k*2,y);
    }
    else
        findy(t,(r+l)/2+1,l,k*2+1,y);
}
void findx(int t,int r,int l,int x,int y){//查詢
    findy(t,1,n,1,y);
    if(r==l)return;
    if((r+l)/2>=x)
        findx(t*2,r,(r+l)/2,x,y);
    else
        findx(t*2+1,(r+l)/2+1,l,x,y);
}
int main(){
    int l,i,t,x1,x2,y1,y2,x,y,c;
    scanf("%d",&t);
    for(l=1;l<=t;l++){
        memset(a,0,sizeof(a));
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%s",s);
            if(*s=='C'){
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                buildx(1,1,n,x1,y1,x2,y2);

            }else{
                ans=0;
                scanf("%d%d",&x,&y);
                findx(1,1,n,x,y);
                printf("%d\n",ans);//輸出
            }
        }
        if(l<t)puts("");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章