UVALive - 6709树套树
题意:给你一个矩阵,q次操作,每次查询长宽l的矩阵最大值a和最小值b,然后把中间点换成floor((a+b)/2),
解法:暴力可过,建n颗线段树暴力更新,但是正解应该是树套树,树套树需要注意的是当建树或修改时pushup操作不能直接搞,要先判断是不是外面层的叶子节点,如果是直接修改,如果不是,应该是从外面层的对应子节点更新过来,因为此时的外层树维护的是x轴区间最大和区间最小,需要从x轴两个更小的区间树合并起来更新
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-8; const int N=800+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int c[N][N],n; struct segtreeinsegtree{ int ma[N<<2][N<<2],mi[N<<2][N<<2]; bool leaf; void pushupx(int id,int rt) { ma[id][rt]=max(ma[id<<1][rt],ma[id<<1|1][rt]); mi[id][rt]=min(mi[id<<1][rt],mi[id<<1|1][rt]); } void pushupy(int id,int rt) { ma[id][rt]=max(ma[id][rt<<1],ma[id][rt<<1|1]); mi[id][rt]=min(mi[id][rt<<1],mi[id][rt<<1|1]); } void buildy(int id,int x,int l,int r,int rt) { if(l==r) { if(leaf)ma[id][rt]=mi[id][rt]=c[x][l]; else pushupx(id,rt);//,printf("%d %d %d %d\n",id,x,ma[id][rt]); return ; } int m=(l+r)>>1; buildy(id,x,ls);buildy(id,x,rs); pushupy(id,rt); } void buildx(int xl,int xr,int rt,int yl,int yr) { if(xl==xr){leaf=1;buildy(rt,xl,yl,yr,1);return ;} int m=(xl+xr)>>1; buildx(xl,m,rt<<1,yl,yr); buildx(m+1,xr,rt<<1|1,yl,yr); leaf=0,buildy(rt,xl,yl,yr,1); } void updatey(int id,int posx,int posy,int c,int l,int r,int rt) { if(l==r) { if(leaf)ma[id][rt]=mi[id][rt]=c; else pushupx(id,rt); return ; } int m=(l+r)>>1; if(posy<=m)updatey(id,posx,posy,c,ls); else updatey(id,posx,posy,c,rs); pushupy(id,rt); } void updatex(int posx,int posy,int c,int l,int r,int rt) { if(l==r){leaf=1;updatey(rt,posx,posy,c,1,n,1);return ;} int m=(l+r)>>1; if(posx<=m)updatex(posx,posy,c,ls); else updatex(posx,posy,c,rs); leaf=0,updatey(rt,posx,posy,c,1,n,1); } int querymay(int id,int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return ma[id][rt]; int m=(l+r)>>1,ans=0; if(L<=m)ans=max(ans,querymay(id,L,R,ls)); if(m<R)ans=max(ans,querymay(id,L,R,rs)); return ans; } int querymax(int xl,int xr,int yl,int yr,int l,int r,int rt) { if(xl<=l&&r<=xr){return querymay(rt,yl,yr,1,n,1);} int m=(l+r)>>1,ans=0; if(xl<=m)ans=max(ans,querymax(xl,xr,yl,yr,ls)); if(m<xr)ans=max(ans,querymax(xl,xr,yl,yr,rs)); return ans; } int querymiy(int id,int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return mi[id][rt]; int m=(l+r)>>1,ans=1e9+10; if(L<=m)ans=min(ans,querymiy(id,L,R,ls)); if(m<R)ans=min(ans,querymiy(id,L,R,rs)); return ans; } int querymix(int xl,int xr,int yl,int yr,int l,int r,int rt) { if(xl<=l&&r<=xr)return querymiy(rt,yl,yr,1,n,1); int m=(l+r)>>1,ans=1e9+10; if(xl<=m)ans=min(ans,querymix(xl,xr,yl,yr,ls)); if(m<xr)ans=min(ans,querymix(xl,xr,yl,yr,rs)); return ans; } int query(int x,int y,int l) { int xl=max(1,x-l/2),xr=min(n,x+l/2); int yl=max(1,y-l/2),yr=min(n,y+l/2); int ma=querymax(xl,xr,yl,yr,1,n,1); int mi=querymix(xl,xr,yl,yr,1,n,1); // printf("%d %d\n",ma,mi); int ans=floor(1.0*(ma+mi)/2); updatex(x,y,ans,1,n,1); return ans; } void debug(int id,int l,int r,int rt) { printf("%d %d %d %d\n",l,r,ma[id][rt],mi[id][rt]); if(l==r)return ; int m=(l+r)>>1; debug(id,ls);debug(id,rs); } }s; int main() { int T,cnt=0;scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&c[i][j]); s.buildx(1,n,1,1,n); // s.debug(5,1,n,1); int q;scanf("%d",&q); printf("Case #%d:\n",++cnt); while(q--) { int x,y,l; scanf("%d%d%d",&x,&y,&l); printf("%d\n",s.query(x,y,l)); } } return 0; } /*********************** 1 3 1 2 3 4 5 6 7 8 9 5 2 2 1 ***********************/