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


题目链接:点击打开链接


题目大意:

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


解题思路:

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

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


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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|1
using 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



你可能感兴趣的:(数据结构---线段树)