HDU-4819: Mosaic(二维线段树(树套树))

来源:互联网 发布:阿里云 系统镜像 上传 编辑:程序博客网 时间:2024/05/17 16:14


题目链接:点击打开链接


题目大意:

刚上来给你一个 n*n 的矩阵,每个坐标有自己的颜色。然后 m 次查询 ,输入 x,y,l .输出以 (x,y)为中心 边长为 l 的正方形的中的最大颜色和最小颜色的平均值。并将(x,y)坐标的值更改为平均值。


解题思路:

就是一道二维线段树,刚开始写的是单点更新和y轴区间查询,t 掉了。后来知道了要让x轴也能实现区间查询。。。不知道怎么写,纠结了好长时间,还是看了别人的博客。

也就是一种比较巧妙地思路,每次更新完之后再把x更新一遍。。。具体看代码吧,有点说说不清楚,


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <vector>#include <queue>#include <map>#include <algorithm>#include <stack>#include <set>#include <functional>#define rank ra#define lxson rt<<1#define lyson rt<<1|1#define pb push_back#define hash haha#define xlson xl,xmid,xt<<1#define xrson xmid+1,xr,xt<<1|1#define ylson yl,ymid,xt,yt<<1#define yrson ymid+1,yr,xt,yt<<1|1using namespace std;typedef long long ll;const int INF=1e9+7;const int N=805;int n,m,ans1,ans2;int ma[N<<2][N<<2],mi[N<<2][N<<2];      //最大值和最小值void pushup(int xt,int yt){    ma[xt][yt]=max(ma[xt][yt<<1],ma[xt][yt<<1|1]);      //维护y轴    mi[xt][yt]=min(mi[xt][yt<<1],mi[xt][yt<<1|1]);}void update_y(int q1,int flag,int yl,int yr,int xt,int yt){    if(q1==yl&&yl==yr)    {        if(flag!=-1)    //正常更新        {            ma[xt][yt]=flag;            mi[xt][yt]=flag;        }        else        {            ma[xt][yt]=max(ma[xt<<1][yt],ma[xt<<1|1][yt]);      //维护x轴            mi[xt][yt]=min(mi[xt<<1][yt],mi[xt<<1|1][yt]);        }        return ;    }    int ymid=(yl+yr)>>1;    if(q1<=ymid)        update_y(q1,flag,ylson);    if(q1>ymid)        update_y(q1,flag,yrson);    pushup(xt,yt);}void update_x(int p1,int q1,int flag,int xl,int xr,int xt){    if(xl==xr)    {        update_y(q1,flag,1,n,xt,1);        return ;    }    int xmid=(xl+xr)>>1;    if(p1<=xmid)        update_x(p1,q1,flag,xlson);    if(p1>xmid)        update_x(p1,q1,flag,xrson);    update_y(q1,-1,1,n,xt,1);       //维护x轴}void query_y(int q1,int q2,int yl,int yr,int xt,int yt){    if(q1<=yl&&yr<=q2)      //区间查询    {        ans1=max(ans1,ma[xt][yt]);        ans2=min(ans2,mi[xt][yt]);        return ;    }    int ymid=(yl+yr)>>1;    if(q1<=ymid)        query_y(q1,q2,ylson);    if(q2>ymid)        query_y(q1,q2,yrson);}void query_x(int p1,int q1,int p2,int q2,int xl,int xr,int xt){    if(p1<=xl&&xr<=p2)      //同上    {        query_y(q1,q2,1,n,xt,1);        return ;    }    int xmid=(xl+xr)>>1;    if(p1<=xmid)        query_x(p1,q1,p2,q2,xlson);    if(p2>xmid)        query_x(p1,q1,p2,q2,xrson);}int main(){    int QAQ,kase=0;    scanf("%d",&QAQ);    while(QAQ--)    {        scanf("%d",&n);        int k;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                scanf("%d",&k);                update_x(i,j,k,1,n,1);  //这一步很费时 预先存图build的话省很多时间            }        }        scanf("%d",&m);        int p1,q1,p2,q2,x,y,l;        printf("Case #%d:\n",++kase);        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&x,&y,&l);            l=(l-1)/2;            p1=max(x-l,1);  //注意边界            p2=min(x+l,n);            q1=max(y-l,1);            q2=min(y+l,n);            ans1=-INF;ans2=INF;            query_x(p1,q1,p2,q2,1,n,1); //查询加更新            int flag=(ans1+ans2)/2;            printf("%d\n",flag);            update_x(x,y,flag,1,n,1);        }    }}



原创粉丝点击