本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Problem Description
The God of sheep decides to pixelate some pictures (i.e., change them into pictures with mosaic). Here‘s how he is gonna make it: for each picture, he divides the picture into n x n cells, where each cell is assigned a color value. Then he chooses a cell, and checks the color values in the L x L region whose center is at this specific cell. Assuming the maximum and minimum color values in the region is A and B respectively, he will replace the color value in the chosen cell with floor((A + B) / 2).
Can you help the
God of sheep?
Input
The first line contains an integer T (T ≤ 5) indicating
the number of test cases. Then T test cases follow.
Each test case begins
with an integer n (5 < n < 800). Then the following n rows describe the
picture to pixelate, where each row has n integers representing the original
color values. The j-th integer in the i-th row is the color value of cell (i, j)
of the picture. Color values are nonnegative integers and will not exceed
1,000,000,000 (10^9).
After the description of the picture, there is an
integer Q (Q ≤ 100000 (10^5)), indicating the number of mosaics.
Then Q
actions follow: the i-th row gives the i-th replacement made by the God of
sheep: xi, yi, Li (1 ≤ xi, yi ≤ n, 1 ≤ Li < 10000, Li is odd). This means the
God of sheep will change the color value in (xi, yi) (located at row xi and
column yi) according to the Li x Li region as described above. For example, an
query (2, 3, 3) means changing the color value of the cell at the second row and
the third column according to region (1, 2) (1, 3), (1, 4), (2, 2), (2, 3), (2,
4), (3, 2), (3, 3), (3, 4). Notice that if the region is not entirely inside the
picture, only cells that are both in the region and the picture are
considered.
Note that the God of sheep will do the replacement one by one
in the order given in the input.
Output
For each test case, print a line "Case #t:"(without
quotes, t means the index of the test case) at the beginning.
For each
action, print the new color value of the updated cell.
Sample Input
1
3
1 2 3
4 5 6
7 8 9
5
2 2 1
3 2 3
1 1 3
1 2 3
2 2 3
Sample Output
Case #1:
5
6
3
4
6
正解:二维线段树
解题报告:
又调了一个晚上的题目…
(每晚留一道题目调不完的debuff...)
二维线段树相当于是维护了一个矩阵,不妨叫做主线段树和副线段树,那么主线段树上的每个节点都存了一棵副线段树(可以动态开节点呀),那么就没有区别了…
只是要注意一点,modify了之后显然不能直接merge两个子树,复杂度是线性的...
直接查询两个子树的这一位,取max/min然后在子树上直接modify即可。
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; typedef long long LL; const int MAXN = 811; const int MAXM = 5000011; int n,m,ju[MAXN][MAXN],X[2],Y[2],cnt,rt,ans,CC; struct node{ int l,r,ls,rs,maxl,minl,tree; }a[MAXM]; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<‘0‘||c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar(); while (c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w; } namespace Seg_tree{ inline void build(int &k,int l,int r,int bel){ k=++cnt; a[k].l=l; a[k].r=r; if(l==r) { a[k].minl=a[k].maxl=ju[l][bel]; return ; } int mid=(l+r)>>1; build(a[k].ls,l,mid,bel); build(a[k].rs,mid+1,r,bel); a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl); a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl); } inline int query_min(int k,int l,int r){ if(Y[0]<=l && r<=Y[1]) return a[k].minl; int mid=(l+r)>>1; if(Y[0]>mid) return query_min(a[k].rs,mid+1,r); else if(Y[1]<=mid) return query_min(a[k].ls,l,mid); else return min(query_min(a[k].ls,l,mid),query_min(a[k].rs,mid+1,r)); } inline int query_max(int k,int l,int r){ if(Y[0]<=l && r<=Y[1]) return a[k].maxl; int mid=(l+r)>>1; if(Y[0]>mid) return query_max(a[k].rs,mid+1,r); else if(Y[1]<=mid) return query_max(a[k].ls,l,mid); else return max(query_max(a[k].ls,l,mid),query_max(a[k].rs,mid+1,r)); } inline void modify(int k,int l,int r,int y){ if(l==r) { a[k].minl=a[k].maxl=ans; return ; } int mid=(l+r)>>1; if(y<=mid) modify(a[k].ls,l,mid,y); else modify(a[k].rs,mid+1,r,y); a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl); a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl); } inline void update_min(int k,int l,int r,int y){ if(l==r) { a[k].minl=CC; return ; } int mid=(l+r)>>1; if(y<=mid) update_min(a[k].ls,l,mid,y); else update_min(a[k].rs,mid+1,r,y); a[k].minl=min(a[a[k].ls].minl,a[a[k].rs].minl); } inline void update_max(int k,int l,int r,int y){ if(l==r) { a[k].maxl=CC; return ; } int mid=(l+r)>>1; if(y<=mid) update_max(a[k].ls,l,mid,y); else update_max(a[k].rs,mid+1,r,y); a[k].maxl=max(a[a[k].ls].maxl,a[a[k].rs].maxl); } } inline void merge(int &k,node q,node qq){ if(!k) k=++cnt; a[k].maxl=max(q.maxl,qq.maxl); a[k].minl=min(q.minl,qq.minl); a[k].l=q.l; a[k].r=q.r; if(q.l==q.r) return ; merge(a[k].ls,a[q.ls],a[qq.ls]); merge(a[k].rs,a[q.rs],a[qq.rs]); } inline void build(int &k,int l,int r){ k=++cnt; a[k].l=l; a[k].r=r; if(l==r) { Seg_tree::build(a[k].tree,1,n,l); return; } int mid=(l+r)>>1; build(a[k].ls,l,mid); build(a[k].rs,mid+1,r); merge(a[k].tree,a[ a[a[k].ls].tree ],a[ a[a[k].rs].tree ]); } inline int query_min(int k,int l,int r){ if(X[0]<=l && r<=X[1]) return Seg_tree::query_min(a[k].tree,1,n); int mid=(l+r)>>1; if(X[0]>mid) return query_min(a[k].rs,mid+1,r); else if(X[1]<=mid) return query_min(a[k].ls,l,mid); else return min(query_min(a[k].ls,l,mid),query_min(a[k].rs,mid+1,r)); } inline int query_max(int k,int l,int r){ if(X[0]<=l && r<=X[1]) return Seg_tree::query_max(a[k].tree,1,n); int mid=(l+r)>>1; if(X[0]>mid) return query_max(a[k].rs,mid+1,r); else if(X[1]<=mid) return query_max(a[k].ls,l,mid); else return max(query_max(a[k].ls,l,mid),query_max(a[k].rs,mid+1,r)); } inline void modify(int k,int l,int r,int x,int y){ if(l==r) { Seg_tree::modify(a[k].tree,1,n,y); return ; } int mid=(l+r)>>1; if(x<=mid) modify(a[k].ls,l,mid,x,y); else modify(a[k].rs,mid+1,r,x,y); int lc=a[k].ls,rc=a[k].rs; int lmin=Seg_tree::query_min(a[lc].tree,a[a[lc].tree].l,a[a[lc].tree].r); int rmin=Seg_tree::query_min(a[rc].tree,a[a[rc].tree].l,a[a[rc].tree].r); CC=min(lmin,rmin); Seg_tree::update_min(a[k].tree,a[a[k].tree].l,a[a[k].tree].r,y); int lmax=Seg_tree::query_max(a[lc].tree,a[a[lc].tree].l,a[a[lc].tree].r); int rmax=Seg_tree::query_max(a[rc].tree,a[a[rc].tree].l,a[a[rc].tree].r); CC=max(lmax,rmax); Seg_tree::update_max(a[k].tree,a[a[k].tree].l,a[a[k].tree].r,y); //merge(a[k].tree,a[ a[a[k].ls].tree ],a[ a[a[k].rs].tree ]); } inline void work(){ int T=getint(); for(int Case=1;Case<=T;Case++) { printf("Case #%d:\n",Case); n=getint(); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ju[i][j]=getint(); for(int i=1;i<=cnt;i++) a[i].tree=a[i].ls=a[i].rs=0; cnt=0; rt=0; build(rt,1,n); m=getint(); int x,y,z,da,xiao; while(m--) { y=getint(); x=getint(); z=getint(); z>>=1; X[0]=max(x-z,1); X[1]=min(x+z,n); Y[0]=max(y-z,1); Y[1]=min(y+z,n); da=query_max(rt,1,n); xiao=query_min(rt,1,n); ans=(da+xiao)>>1; printf("%d\n",ans); Y[0]=Y[1]=y; modify(rt,1,n,x,y); } } } int main() { work(); return 0; }