2155 Matrix 二维线段树

Matrix
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 7121 Accepted: 2657

Description

Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1 <= i, j <= N).

We can change the matrix in the following way. Given a rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2), we change all the elements in the rectangle by using "not" operation (if it is a '0' then change it into '1' otherwise change it into '0'). To maintain the information of the matrix, you are asked to write a program to receive and execute two kinds of instructions.

1. C x1 y1 x2 y2 (1 <= x1 <= x2 <= n, 1 <= y1 <= y2 <= n) changes the matrix by using the rectangle whose upper-left corner is (x1, y1) and lower-right corner is (x2, y2).
2. Q x y (1 <= x, y <= n) querys A[x, y].

Input

The first line of the input is an integer X (X <= 10) representing the number of test cases. The following X blocks each represents a test case.

The first line of each block contains two numbers N and T (2 <= N <= 1000, 1 <= T <= 50000) representing the size of the matrix and the number of the instructions. The following T lines each represents an instruction having the format "Q x y" or "C x1 y1 x2 y2", which has been described above.

Output

For each querying output one line, which has an integer representing A[x, y].

There is a blank line between every two continuous test cases.

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

Source

POJ Monthly,Lou Tiancheng

 

 

 

#include<stdio.h>
#define LL(x)  (x<<1)
#define RR(x) (x<<1|1)
int n,sum;
struct Seg_Seg_Tree
{
    int left,right;
    bool val;
    int mid() { return (left+right)>>1; }
};
struct Seg_Tree
{
    int left,right;
    Seg_Seg_Tree tt[1010*3];
    int mid() { return(left+right)>>1;}
}tree[1010*3];
void build2(Seg_Seg_Tree t[],int left,int right,int idx)
{
    t[idx].left=left;
    t[idx].right=right;
    t[idx].val=false;
    if(left==right)  return;
    int mid=t[idx].mid();
    build2(t,left,mid,LL(idx));
    build2(t,mid+1,right,RR(idx));
}
void build(int left,int right,int idx)
{
    build2(tree[idx].tt,1,n,1);
    tree[idx].left=left;
    tree[idx].right=right;
    if(left==right)  return;
    int mid=tree[idx].mid();
    build(left,mid,LL(idx));
    build(mid+1,right,RR(idx));
}

void update2(Seg_Seg_Tree t[],int idx,int left,int right,int y1,int y2)
{
    if(y1==left&&y2==right)
    {
        t[idx].val=!t[idx].val;
        return;
    }
    int mid=t[idx].mid();
    if (y2 <= mid)  update2(t, LL(idx), left, mid, y1, y2);
    else if (y1 > mid) update2(t, RR(idx), mid+1, right, y1, y2);
    else
    {
           update2(t, LL(idx), left, mid, y1, mid);
           update2(t, RR(idx), mid+1, right, mid+1, y2);
    }
}

void update(int idx,int left,int right,int x1,int x2,int y1,int y2)
{
    if(x1==left&&x2==right)
    {
        update2(tree[idx].tt,1,1,n,y1,y2);
        return;
    }
    int mid=tree[idx].mid();
    if (x2 <= mid) update(LL(idx), left, mid, x1, x2, y1, y2);
    else if (x1 > mid) update(RR(idx), mid+1, right, x1, x2, y1, y2);
    else
    {
            update(LL(idx), left, mid, x1, mid, y1, y2);
            update(RR(idx), mid+1, right, mid+1, x2, y1, y2);
    }
}

void query2(Seg_Seg_Tree t[],int idx,int first, int last,int y)
{
    sum ^= t[idx].val;
    if (first < last)
    {
        int mid = t[idx].mid();
        if (y <= mid)
            query2(t, LL(idx), first, mid, y);
        else
            query2(t, RR(idx), mid+1, last, y);
    }
}

void query(int idx,int first,int last,int x,int y)
{
     query2(tree[idx].tt,1,1,n,y);
     if (first < last)
     {
        int mid = tree[idx].mid();
        if (x <= mid)
            query(LL(idx), first, mid, x, y);
        else
            query(RR(idx), mid+1, last, x, y);
     }
}

int main()
{
    int TT;
    scanf("%d",&TT);
    for(int j=0;j<TT;j++)
    {
        int t;
        if(j>0)  printf("/n");
        scanf("%d%d",&n,&t);
        build(1,n,1);
        for(int i=1;i<=t;i++)
        {
            char str[10];
            scanf("%s",str);
            if(str[0]=='C')
            {
                int x1,y1,x2,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                update(1,1,n,x1,x2,y1,y2);
            }
            else
            {
                int x,y;
                scanf("%d%d",&x,&y);
                sum=0;
                query(1,1,n,x,y);
                printf("%d/n", sum);
            }
        }
    }
    return 0;
}

 

 

数组做法

#include <stdio.h>

#include <string.h>

#define MAXN 3010

#define LL(x) (x<<1)

#define RR(x) (x<<1|1)

int g[MAXN][MAXN],n,m,x,y,z,l,ans;

void updataY(int xid ,int id,int lf,int rg)

{

    if( z<=lf && rg<=l)

    {

        if(g[xid][id]==1) g[xid][id]=0;

        else g[xid][id]=1;

        return;

    }

    int mid = ( lf + rg)>>1;

    if( z < mid )  updataY(xid , LL(id) , lf ,mid);

    if( mid < l )   updataY(xid ,RR(id), mid ,rg);

}

void updateX(int id,int lf,int rg)

{

    if( x<=lf && rg<=y)

    {

        if(g[id][0]==-1) g[id][0]=0;

        updataY( id , 1 , 0, n);

        return;

    }

    int mid = ( lf + rg)>>1;

    if(x<mid)  updateX(LL(id),lf,mid);

    if(mid<y)  updateX(RR(id),mid,rg);

}

void queryY(int xid ,int id,int lf,int rg)

{

    if( g[xid][id] != -1)

        ans^=g[xid][id];

    if( z<=lf && rg<=l)  return;

    int mid = ( lf + rg)>>1;

    if( z < mid ) queryY(xid , LL(id), lf ,mid);

    if( mid < l ) queryY(xid ,RR(id), mid ,rg);

}

void queryX(int id,int lf,int rg)

{

    if( !g[id][0] ) queryY(id,1,0,n);

    if( x<=lf && rg<=y) return ;

    int mid = ( lf + rg)>>1;

    if(x<mid) queryX(LL(id),lf,mid);

    if(mid<y) queryX(RR(id),mid,rg);

}

int main()

{

    int kase,f=0;

    char in[10];

    scanf("%d",&kase );

    while( kase-- )

    {

        if(!f) f=1;

        else puts("");

        scanf("%d%d", &n, &m);

        memset( g, -1, sizeof(g));

        while(m--)

        {

            scanf("%s",in);

            if( in[0] == 'C')

            {

                scanf("%d%d%d%d",&x,&z,&y,&l);

                x--,z--;

                updateX(1,0,n);

            }

            else

            {

                scanf("%d%d",&y,&l);

                x=y-1;

                z=l-1;

                ans=0;

                queryX(1,0,n);

                printf("%d/n",ans);

            }

        }

    }

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值