题目大意:
给出一个矩阵,有一种操作:x,y,l,将(x,y)元素修改为,以(x,y)为中心,尺寸为l*l的矩阵中(min+max)/2。
就是一个裸的二维线段树,一维是普通线段树,二维每个区间都有一个线段树。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define L(x) (x)<<1 #define R(x) ((x)<<1)|1 #define N 810 const int INF=0x3f3f3f3f; using namespace std; int n; struct y { int l,r,mi,ma; }; struct x { int l,r; y cy[N*4]; void bulid(int i,int ll,int rr) { cy[i].l=ll,cy[i].r=rr,cy[i].mi=INF,cy[i].ma=-INF; if(ll==rr) return ; int mid=(ll+rr)/2; bulid(L(i),ll,mid); bulid(R(i),mid+1,rr); } int queryMin(int i,int ll,int rr) { if(ll==cy[i].l&&rr==cy[i].r) return cy[i].mi; int mid=(cy[i].l+cy[i].r)/2; if(rr<=mid) return queryMin(L(i),ll,rr); else if(ll>mid) return queryMin(R(i),ll,rr); else return min(queryMin(L(i),ll,mid),queryMin(R(i),mid+1,rr)); } int queryMax(int i,int ll,int rr) { if(ll==cy[i].l&&rr==cy[i].r) return cy[i].ma; int mid=(cy[i].l+cy[i].r)/2; if(rr<=mid) return queryMax(L(i),ll,rr); else if(ll>mid) return queryMax(R(i),ll,rr); else return max(queryMax(L(i),ll,mid),queryMax(R(i),mid+1,rr)); } }cx[N*4]; void Bulid(int i,int l,int r) { cx[i].l=l,cx[i].r=r; cx[i].bulid(1,1,n); if(l==r) return ; int mid=(l+r)/2; Bulid(L(i),l,mid); Bulid(R(i),mid+1,r); } void update_1D(int j,int i,int x,int y,int val) { if(y==cx[j].cy[i].l&&y==cx[j].cy[i].r){ if(cx[j].l==cx[j].r) { cx[j].cy[i].mi=cx[j].cy[i].ma=val; } else{ int mid=(cx[j].l+cx[j].r)/2; cx[j].cy[i].mi=min(cx[L(j)].cy[i].mi,cx[R(j)].cy[i].mi); cx[j].cy[i].ma=max(cx[L(j)].cy[i].ma,cx[R(j)].cy[i].ma); } } else { int mid=(cx[j].cy[i].l+cx[j].cy[i].r)/2; if(y<=mid) update_1D(j,L(i),x,y,val); else update_1D(j,R(i),x,y,val); cx[j].cy[i].mi=min(cx[j].cy[L(i)].mi,cx[j].cy[R(i)].mi); cx[j].cy[i].ma=max(cx[j].cy[L(i)].ma,cx[j].cy[R(i)].ma); } } void update_2D(int i,int x,int y,int val) { if(cx[i].l==x&&cx[i].r==x) { update_1D(i,1,x,y,val); } if(cx[i].l==cx[i].r) return ; int mid=(cx[i].l+cx[i].r)/2; if(x<=mid) update_2D(L(i),x,y,val); else update_2D(R(i),x,y,val); update_1D(i,1,x,y,val); } int QueryMin(int i,int x1,int x2,int y1,int y2) { if(cx[i].l==x1&&cx[i].r==x2) return cx[i].queryMin(1,y1,y2); //if(cx[i].l==cx[i].r) return cx[i].queryMin(1,y1,y2); int mid=(cx[i].l+cx[i].r)/2; if(x2<=mid) return QueryMin(L(i),x1,x2,y1,y2); else if(x1>mid) return QueryMin(R(i),x1,x2,y1,y2); else return min(QueryMin(L(i),x1,mid,y1,y2),QueryMin(R(i),mid+1,x2,y1,y2)); } int QueryMax(int i,int x1,int x2,int y1,int y2) { if(cx[i].l==x1&&cx[i].r==x2) return cx[i].queryMax(1,y1,y2); //if(cx[i].l==cx[i].r) return cx[i].queryMin(1,y1,y2); int mid=(cx[i].l+cx[i].r)/2; if(x2<=mid) return QueryMax(L(i),x1,x2,y1,y2); else if(x1>mid) return QueryMax(R(i),x1,x2,y1,y2); else return max(QueryMax(L(i),x1,mid,y1,y2),QueryMax(R(i),mid+1,x2,y1,y2)); } int main() { #ifndef ONLINE_JUDGE freopen("D:/in.txt","r",stdin); #endif // ONLINE_JUDGE int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d",&n); printf("Case #%d:\n",cas++); Bulid(1,1,n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { int a; scanf("%d",&a); update_2D(1,i,j,a); } int q; scanf("%d",&q); for(int i=0;i<q;i++) { int x,y,l; scanf("%d%d%d",&x,&y,&l); int x1=max(x-l/2,1); int x2=min(x+l/2,n); int y1=max(y-l/2,1); int y2=min(y+l/2,n); int mi=QueryMin(1,x1,x2,y1,y2); int ma=QueryMax(1,x1,x2,y1,y2); int val=(mi+ma)/2; update_2D(1,x,y,val); printf("%d\n",val); } } return 0; }