HDU 4819 Mosaic
2014-06-30 19:44
155 查看
题意:
一个矩形内每个格子都有一个值 现在有q个操作 每个操作给出坐标(x,y)和长度L 每次操作输出以(x,y)为中心的边长为L的矩形内的最大值和最小值之和的一半 并将这个值更新到(x,y)坐标上
思路:
区间查询最大最小值 单点更新 明显是线段树的特征 不过这里是二维的线段树 我用的是树套树的写法
我对二维线段树的理解:(个人理解不一定正确)
初始化麻烦 相当于做n*n次单点更新
树套树操作的思维就先找到满足第一位的区间 这个区间对应几棵树 然后在这几棵树(即第二维)里面操作
建树、查询相对简单 就按上面说的分开两维做就好
更新较麻烦 如果要更新(x,y) 需要先在第一维找到x 然后将x对应的第二维的y赋值 接着up操作(此时代表更新完了第一维为(x,x)的区间) 最后在第一维上更新 就是x更新好后利用(x,y)去更新包含x的所有第一维区间(有点难说 代码比较清晰)
PS:
当初长春坑了这题… 竟然一年以后才开始补… 还整整敲了一下午!!
我对自己也没话说…
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 2147483647
#define N 805
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
#define Mid(x,y) ((x+y)>>1)
struct nodey
{
int l,r,minval,maxval;
};
struct nodex
{
int l,r;
nodey y[N*4];
}x[N*4];
int n,q,lx,ly,ll;
void inity(int l,int r,int i,int j)
{
x[j].y[i].l=l; x[j].y[i].r=r; x[j].y[i].minval=inf; x[j].y[i].maxval=-inf;
if(l==r) return ;
inity(l,Mid(l,r),L(i),j);
inity(Mid(l,r)+1,r,R(i),j);
}
void initx(int l,int r,int i)
{
x[i].l=l; x[i].r=r;
inity(1,n,1,i);
if(l==r) return ;
initx(l,Mid(l,r),L(i));
initx(Mid(l,r)+1,r,R(i));
}
int maxans,minans;
void queryy(int l,int r,int i,int j)
{
if(x[j].y[i].l==l&&x[j].y[i].r==r)
{
maxans=max(maxans,x[j].y[i].maxval);
minans=min(minans,x[j].y[i].minval);
return ;
}
int mid=Mid(x[j].y[i].l,x[j].y[i].r);
if(r<=mid) queryy(l,r,L(i),j);
else if(l>mid) queryy(l,r,R(i),j);
else
{
queryy(l,mid,L(i),j);
queryy(mid+1,r,R(i),j);
}
}
void queryx(int l,int r,int i)
{
if(x[i].l==l&&x[i].r==r)
{
queryy(max(1,ly-ll/2),min(n,ly+ll/2),1,i);
return ;
}
int mid=Mid(x[i].l,x[i].r);
if(r<=mid) queryx(l,r,L(i));
else if(l>mid) queryx(l,r,R(i));
else
{
queryx(l,mid,L(i));
queryx(mid+1,r,R(i));
}
}
void updatey(int l,int i,int j,int key)
{
if(x[j].y[i].l==x[j].y[i].r)
{
if(x[j].l==x[j].r)
{
x[j].y[i].minval=key;
x[j].y[i].maxval=key;
}
else
{
x[j].y[i].minval=min(x[L(j)].y[i].minval,x[R(j)].y[i].minval);
x[j].y[i].maxval=max(x[L(j)].y[i].maxval,x[R(j)].y[i].maxval);
}
return ;
}
int mid=Mid(x[j].y[i].l,x[j].y[i].r);
if(l<=mid) updatey(l,L(i),j,key);
else updatey(l,R(i),j,key);
x[j].y[i].minval=min(x[j].y[L(i)].minval,x[j].y[R(i)].minval);
x[j].y[i].maxval=max(x[j].y[L(i)].maxval,x[j].y[R(i)].maxval);
}
void updatex(int l,int i,int key)
{
if(x[i].l==x[i].r)
{
updatey(ly,1,i,key);
return ;
}
int mid=Mid(x[i].l,x[i].r);
if(l<=mid) updatex(l,L(i),key);
else updatex(l,R(i),key);
updatey(ly,1,i,key);
}
int main()
{
int t,i,j,k,tmp;
scanf("%d",&t);
for(k=1;k<=t;k++)
{
scanf("%d",&n);
initx(1,n,1);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&tmp);
ly=j;
updatex(i,1,tmp);
}
}
scanf("%d",&q);
printf("Case #%d:\n",k);
while(q--)
{
scanf("%d%d%d",&lx,&ly,&ll);
minans=inf; maxans=-inf;
queryx(max(1,lx-ll/2),min(n,lx+ll/2),1);
tmp=Mid(maxans,minans);
printf("%d\n",tmp);
updatex(lx,1,tmp);
}
}
return 0;
}
一个矩形内每个格子都有一个值 现在有q个操作 每个操作给出坐标(x,y)和长度L 每次操作输出以(x,y)为中心的边长为L的矩形内的最大值和最小值之和的一半 并将这个值更新到(x,y)坐标上
思路:
区间查询最大最小值 单点更新 明显是线段树的特征 不过这里是二维的线段树 我用的是树套树的写法
我对二维线段树的理解:(个人理解不一定正确)
初始化麻烦 相当于做n*n次单点更新
树套树操作的思维就先找到满足第一位的区间 这个区间对应几棵树 然后在这几棵树(即第二维)里面操作
建树、查询相对简单 就按上面说的分开两维做就好
更新较麻烦 如果要更新(x,y) 需要先在第一维找到x 然后将x对应的第二维的y赋值 接着up操作(此时代表更新完了第一维为(x,x)的区间) 最后在第一维上更新 就是x更新好后利用(x,y)去更新包含x的所有第一维区间(有点难说 代码比较清晰)
PS:
当初长春坑了这题… 竟然一年以后才开始补… 还整整敲了一下午!!
我对自己也没话说…
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 2147483647
#define N 805
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
#define Mid(x,y) ((x+y)>>1)
struct nodey
{
int l,r,minval,maxval;
};
struct nodex
{
int l,r;
nodey y[N*4];
}x[N*4];
int n,q,lx,ly,ll;
void inity(int l,int r,int i,int j)
{
x[j].y[i].l=l; x[j].y[i].r=r; x[j].y[i].minval=inf; x[j].y[i].maxval=-inf;
if(l==r) return ;
inity(l,Mid(l,r),L(i),j);
inity(Mid(l,r)+1,r,R(i),j);
}
void initx(int l,int r,int i)
{
x[i].l=l; x[i].r=r;
inity(1,n,1,i);
if(l==r) return ;
initx(l,Mid(l,r),L(i));
initx(Mid(l,r)+1,r,R(i));
}
int maxans,minans;
void queryy(int l,int r,int i,int j)
{
if(x[j].y[i].l==l&&x[j].y[i].r==r)
{
maxans=max(maxans,x[j].y[i].maxval);
minans=min(minans,x[j].y[i].minval);
return ;
}
int mid=Mid(x[j].y[i].l,x[j].y[i].r);
if(r<=mid) queryy(l,r,L(i),j);
else if(l>mid) queryy(l,r,R(i),j);
else
{
queryy(l,mid,L(i),j);
queryy(mid+1,r,R(i),j);
}
}
void queryx(int l,int r,int i)
{
if(x[i].l==l&&x[i].r==r)
{
queryy(max(1,ly-ll/2),min(n,ly+ll/2),1,i);
return ;
}
int mid=Mid(x[i].l,x[i].r);
if(r<=mid) queryx(l,r,L(i));
else if(l>mid) queryx(l,r,R(i));
else
{
queryx(l,mid,L(i));
queryx(mid+1,r,R(i));
}
}
void updatey(int l,int i,int j,int key)
{
if(x[j].y[i].l==x[j].y[i].r)
{
if(x[j].l==x[j].r)
{
x[j].y[i].minval=key;
x[j].y[i].maxval=key;
}
else
{
x[j].y[i].minval=min(x[L(j)].y[i].minval,x[R(j)].y[i].minval);
x[j].y[i].maxval=max(x[L(j)].y[i].maxval,x[R(j)].y[i].maxval);
}
return ;
}
int mid=Mid(x[j].y[i].l,x[j].y[i].r);
if(l<=mid) updatey(l,L(i),j,key);
else updatey(l,R(i),j,key);
x[j].y[i].minval=min(x[j].y[L(i)].minval,x[j].y[R(i)].minval);
x[j].y[i].maxval=max(x[j].y[L(i)].maxval,x[j].y[R(i)].maxval);
}
void updatex(int l,int i,int key)
{
if(x[i].l==x[i].r)
{
updatey(ly,1,i,key);
return ;
}
int mid=Mid(x[i].l,x[i].r);
if(l<=mid) updatex(l,L(i),key);
else updatex(l,R(i),key);
updatey(ly,1,i,key);
}
int main()
{
int t,i,j,k,tmp;
scanf("%d",&t);
for(k=1;k<=t;k++)
{
scanf("%d",&n);
initx(1,n,1);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%d",&tmp);
ly=j;
updatex(i,1,tmp);
}
}
scanf("%d",&q);
printf("Case #%d:\n",k);
while(q--)
{
scanf("%d%d%d",&lx,&ly,&ll);
minans=inf; maxans=-inf;
queryx(max(1,lx-ll/2),min(n,lx+ll/2),1);
tmp=Mid(maxans,minans);
printf("%d\n",tmp);
updatex(lx,1,tmp);
}
}
return 0;
}
相关文章推荐
- 【HDU 4819】Mosaic 二维线段树模板
- HDU 4819 Mosaic 【二维线段树】
- HDU 4819 Mosaic 二维线段树
- HDU 4819 Mosaic --二维线段树(树套树)
- HDU 4819 Mosaic (二维线段树)
- HDU 4819 Mosaic(二维线段树)
- 二维线段树(Mosaic,hdu 4819)
- HDU 4819 Mosaic (二维线段树)
- HDU 4819 Mosaic 二维线段树
- HDU-4819: Mosaic(二维线段树(树套树))
- HDU-4819-Mosaic
- HDU 4819 Mosaic(二维线段树)
- hdu 4819 Mosaic (二维线段树)
- HDU-4819 Mosaic (二维线段树)(2013 Asia Regional Changchun)
- hdu4819 Mosaic(二维线段树)
- HDU 4819 Mosaic (二维线段树)
- HDU 4819 —— Mosaic(二维线段树)
- hdu 4819 Mosaic【二维线段树】
- HDU 4819 Mosaic D区段树
- HDU 4819 Mosaic 二维线段树