1. 程式人生 > >poj 2155 matrix 二維線段樹 線段樹套線段樹

poj 2155 matrix 二維線段樹 線段樹套線段樹

題意

一個$n*n$矩陣,初始全為0,每次翻轉一個子矩陣,然後單點查詢

題解

任意一種能維護二維平面的資料結構都可以

我這裡寫的是二維線段樹,
因為四分樹的寫法複雜度可能會退化,因此考慮用樹套樹實現二維線段樹

簡單來說就是每個點都維護了一顆線段樹...

因為二維線段樹難以實現pushdown,而他的查詢又是單點的

於是具體思路類似標記永久化,記錄經過的點上的修改次數,最後判斷修改次數的奇偶性即可

//為什麼不寫建構函式和vector?

//因為這是神奇的poj...

#include<iostream>
#include<string>
#include<vector>
#include<string.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define fi first
#define se second
#define mp make_pair
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define IO ios::sync_with_stdio(false)
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
#define forn(ii,x) for(int ii=head[x];ii;ii=e[ii].next)
using namespace std;
const int maxn=4e3+10,maxm=2e6+10;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
int casn,n,m,k,d;
class sstree{
#define nd  node[nowx][nowy]
  public:
  struct segnode {int val;};
//  vector<vector<segnode> > node;
  int n,m,x1,x2,y1,y2,x,nowx;
	int ans;
	segnode node[maxn][maxn];
  void init(int nn,int mm) {
  	n=nn,m=mm;
		memset(node ,0,sizeof node);
//  	node.resize(n*4+10);
//		rep(i,0,(n*4+9)) node[i].resize(m*4+10);
	}
  void update(int xx1,int xx2,int yy1,int yy2){
    x1=xx1,y1=yy1,x2=xx2,y2=yy2;
    updatex(1,n);
  }
  void updatey(int l,int r,int nowy=1){
    if(y1>r||y2<l) return ;
    if(y1<=l&&y2>=r){nd.val^=1;return ;}
    updatey(l,(l+r)>>1,nowy<<1); updatey(((l+r)>>1)+1,r,nowy<<1|1);
  }
  void updatex(int l,int r,int now=1){
    if(x1>r||x2<l) return ;
    if(x1<=l&&x2>=r) {nowx=now;updatey(1,m);return ;}
    updatex(l,(l+r)>>1,now<<1); updatex(((l+r)>>1)+1,r,now<<1|1);
  }
  int query(int xx,int yy){
    x1=xx,y1=yy;ans=0;
    queryx(1,n);
    return ans;
  }
  void queryy(int l,int r,int nowy=1){
    if(y1>r||y1<l) return ;
    ans^=nd.val;
    if(l==r) return ;
    queryy(l,(l+r)>>1,nowy<<1);queryy(((l+r)>>1)+1,r,nowy<<1|1);
  }
  void queryx(int l,int r,int now=1){
		if(x1>r||x1<l) return ;
    nowx=now;queryy(1,m);
		if(l==r) return ;
    queryx(l,(l+r)>>1,now<<1);queryx(((l+r)>>1)+1,r,now<<1|1);
  }
}tree;
int main() {
	IO;
	cin>>casn;
	register int a,b,c,d;
	string s;
	while(casn--){
		cin>>n>>m;
		tree.init(n,n);
		while(m--){
			cin>>s;
			if(s[0]=='C') {
				cin>>a>>b>>c>>d;
				tree.update(a,c,b,d);
			}else {
				cin>>a>>b;
				cout<<tree.query(a,b)<<endl;
			}
		}
		if(casn) cout<<endl;
	}
}