题目链接:HDU4819
【题意】给出一个N*N(N<=800)的矩阵,对于Q(<=100000)次查询(x,y,l)表示以点(x,y)为矩阵中心,长度为l的矩阵中找出最大值A和最小值B,输出C = (A+B)/2;然后把点(x,y)修改为C;
【分析】Q有10^5,所以需要用二维线段树,复杂度Q*log(n)*log(n);就是二维线段树的模板题了;没什么好说的吧,注意下求子矩阵时不要超出范围就好了。我用了树套树的写法。
【AC CODE】1092ms
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_set>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
#include <ctime>
using namespace std;
typedef unsigned int LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 800+10;
int a[MAXN][MAXN],n;
int mx[MAXN<<1][MAXN<<1], mi[MAXN<<1][MAXN<<1];
inline int id(int x, int y){return x+y|x!=y;}
void push_up(int x, int y, int m, int u)
{
mx[u][id(x,y)] = max(mx[u][id(x,m)], mx[u][id(m+1,y)]);
mi[u][id(x,y)] = min(mi[u][id(x,m)], mi[u][id(m+1,y)]);
}
void bulid2(int x, int y, int ux, int uy, bool yz)
{
if(x == y)
{
int u = id(ux,uy);
if(yz) mx[u][id(x,y)] = mi[u][id(x,y)] = a[ux][x];
else
{
int m = (ux+uy)>>1;
mx[u][id(x,y)] = max(mx[id(ux,m)][id(x,y)], mx[id(m+1,uy)][id(x,y)]);
mi[u][id(x,y)] = min(mi[id(ux,m)][id(x,y)], mi[id(m+1,uy)][id(x,y)]);
}
return;
}
int m = (x+y)>>1;
bulid2(x,m,ux,uy,yz);
bulid2(m+1,y,ux,uy,yz);
push_up(x,y,m,id(ux,uy));
}
void bulid(int x, int y)
{
if(x == y)
{
bulid2(1,n,x,y,1);
return;
}
int m = (x+y)>>1;
bulid(x,m);
bulid(m+1,y);
bulid2(1,n,x,y,0);
}
void update2(int x, int y, int p, int v,int ux, int uy, bool yz)
{
if(x == y)
{
int u = id(ux,uy);
if(yz) mx[u][id(x,y)] = mi[u][id(x,y)] = v;
else
{
int m = (ux+uy)>>1;
mx[u][id(x,y)] = max(mx[id(ux,m)][id(x,y)], mx[id(m+1,uy)][id(x,y)]);
mi[u][id(x,y)] = min(mi[id(ux,m)][id(x,y)], mi[id(m+1,uy)][id(x,y)]);
}
return;
}
int m = (x+y)>>1;
if(p <= m) update2(x,m,p,v,ux,uy,yz);
else update2(m+1,y,p,v,ux,uy,yz);
push_up(x,y,m,id(ux,uy));
}
void update(int x, int y, int p, int p2, int v)
{
if(x == y)
{
update2(1,n,p2,v,x,y,1);
return;
}
int m = (x+y)>>1;
if(p <= m) update(x,m,p,p2,v);
else update(m+1,y,p,p2,v);
update2(1,n,p2,v,x,y,0);
}
int qmx,qmi;
void query2(int x, int y, int ql, int qr, int u)
{
if(ql <= x && y <= qr)
{
qmx = max(qmx,mx[u][id(x,y)]);
qmi = min(qmi,mi[u][id(x,y)]);
return;
}
int m = (x+y)>>1;
if(ql <= m) query2(x,m,ql,qr,u);
if(qr > m) query2(m+1,y,ql,qr,u);
}
void query(int x, int y, int ql, int qr, int sl, int sr)
{
if(ql <= x && y <= qr)
{
query2(1,n,sl,sr,id(x,y));
return;
}
int m = (x+y)>>1;
if(ql <= m) query(x,m,ql,qr,sl,sr);
if(qr > m) query(m+1,y,ql,qr,sl,sr);
}
int main()
{
#ifdef SHY
freopen("d://1.txt", "r", stdin);
#endif
int t,count = 0;
scanf("%d%*c", &t);
while(t--)
{
scanf("%d%*c", &n);
repe(i,1,n)
{
repe(j,1,n) scanf("%d%*c", &a[i][j]);
}
bulid(1,n);
int q;
scanf("%d%*c", &q);
printf("Case #%d:\n",++count);
while(q--)
{
qmx = -INF, qmi = INF;
int x,y,r;
scanf("%d %d %d%*c", &x, &y, &r);
r >>= 1;
int ql,qr,sl,sr;
ql = x-r, qr = x+r;
sl = y-r, sr = y+r;
if(ql < 1) ql = 1;
if(qr > n) qr = n;
if(sl < 1) sl = 1;
if(sr > n) sr = n;
query(1,n,ql,qr,sl,sr);
int v = (qmx+qmi)>>1;
printf("%d\n", v);
update(1,n,x,y,v);
}
}
return 0;
}