zoukankan      html  css  js  c++  java
  • HDU 4819 Mosaic --二维线段树(树套树)

    题意: 给一个矩阵,每次查询一个子矩阵内的最大最小值,然后更新子矩阵中心点为(Max+Min)/2.

    解法: 由于是矩阵,且要求区间最大最小和更新单点,很容易想到二维的线段树,可是因为之前没写过二维的线段树,所以没跳出来。后来熟悉了一下,原来很多细节地方都没有考虑到。

    这里build,update,query都分为两个函数,第一个为Y轴的(sub_update),第二个为X轴的(update),不仅每个sub_update或sub_build后面要加Y轴的pushup函数,而且每个update或build函数最后也要进行pushup,只不过是X轴的pushup,写成 sub_build(rt,-1,1,n,1) 或 sub_update(rt,-1,1,n,1);

    二维线段树就是这里比较费解一点,我感觉, 其他地方还比较好理解。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #define Mod 1000000007
    #define lll __int64
    using namespace std;
    #define N 100007
    
    struct sub_seg{
        lll maxi,mini;
    };
    
    struct seg{
        sub_seg st[810<<2];
    }tt[810<<2];
    int n;
    lll Max,Min;
    
    void pushup(int xrt,int rt)
    {
        tt[xrt].st[rt].maxi = max(tt[xrt].st[rt<<1].maxi,tt[xrt].st[rt<<1|1].maxi);
        tt[xrt].st[rt].mini = min(tt[xrt].st[rt<<1].mini,tt[xrt].st[rt<<1|1].mini);
    }
    
    void sub_build(int xrt,int posY,int l,int r,int rt)
    {
        if(l == r)
        {
            if(posY != -1)
            {
                scanf("%I64d",&tt[xrt].st[rt].maxi);
                tt[xrt].st[rt].mini = tt[xrt].st[rt].maxi;
            }
            else
            {
                tt[xrt].st[rt].maxi = max(tt[xrt<<1].st[rt].maxi,tt[xrt<<1|1].st[rt].maxi);
                tt[xrt].st[rt].mini = min(tt[xrt<<1].st[rt].mini,tt[xrt<<1|1].st[rt].mini);
            }
             return;
        }
        int mid = (l + r) >> 1;
        sub_build(xrt,posY, l,mid, 2*rt);
        sub_build(xrt,posY, mid+1,r, 2*rt+1);
        pushup(xrt,rt);         //pushup Y
    }
    
    void build(int l, int r, int rt)
    {
        if(l == r)
        {
            sub_build(rt,l,1,n,1);
            return;
        }
        int mid = (l + r) >> 1;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
        sub_build(rt,-1,1,n,1);  //pushup X
    }
    
    void sub_update(int xrt,int pos,int y,int l,int r,int val,int rt)
    {
        if(l == r)
        {
            if(pos!=-1)
                tt[xrt].st[rt].maxi = tt[xrt].st[rt].mini = val;
            else
            {
                tt[xrt].st[rt].maxi = max(tt[xrt<<1].st[rt].maxi,tt[xrt<<1|1].st[rt].maxi);
                tt[xrt].st[rt].mini = min(tt[xrt<<1].st[rt].mini,tt[xrt<<1|1].st[rt].mini);
            }
            return;
        }
        int mid = (l+r) >> 1 ;
        if(y <= mid)  sub_update(xrt, pos, y, l,mid, val, rt<<1) ;
        else          sub_update(xrt, pos, y, mid+1,r, val, rt<<1|1) ;
        pushup(xrt,rt);                     //pushup Y维
    }
    
    void update(int x,int y,int l,int r,int val,int rt)  //单点更新
    {
        if(l == r)
        {
            sub_update(rt,l,y,1,n,val,1);
            return;
        }
        int mid = (l+r) >> 1;
        if(x<=mid)  update(x,y, l,mid, val, rt<<1);
        else        update(x,y, mid+1,r, val, rt<<1|1);
        sub_update(rt,-1,y,1,n,val,1);      //pushup X维
    }
    
    void sub_query(int xrt,int aa,int bb,int l,int r,int rt)
    {
        if(aa <= l && bb >= r)
        {
            Max = max(Max,tt[xrt].st[rt].maxi);
            Min = min(Min,tt[xrt].st[rt].mini);
            return;
        }
        int mid = (l+r)>>1;
        if(aa<=mid)  sub_query(xrt,aa,bb,l,mid, rt<<1);
        if(bb>mid)   sub_query(xrt,aa,bb,mid+1,r, rt<<1|1);
    }
    
    void query(int l,int r,int aa,int bb,int L1,int R1,int rt)
    {
        if(aa <= l && bb >= r)
        {
            sub_query(rt,L1,R1,1,n,1);
            return;
        }
        int mid = (l+r)>>1;
        if(aa <= mid)  query(l,mid,aa,bb,L1,R1, rt<<1);
        if(bb > mid)   query(mid+1,r,aa,bb,L1,R1, rt<<1|1);
    }
    
    int main()
    {
        int t,i,j,m,x,y,L,cs = 1;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            build(1,n,1);
            scanf("%d",&m);
            printf("Case #%d:
    ",cs++);
            while(m--)
            {
                scanf("%d%d%d",&x,&y,&L);
                int Lx = max(1,x-L/2);
                int Ly = max(1,y-L/2);
                int Rx = min(n,x+L/2);
                int Ry = min(y+L/2,n);
                Max = -1, Min = Mod;
                query(1,n,Lx,Rx,Ly,Ry,1);
                lll mid = (Max+Min)/2LL;
                printf("%I64d
    ",mid);
                update(x,y,1,n,mid,1);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 1469 COURSES 二分图最大匹配
    POJ 1325 Machine Schedule 二分图最大匹配
    USACO Humble Numbers DP?
    SGU 194 Reactor Cooling 带容量上下限制的网络流
    POJ 3084 Panic Room 求最小割
    ZOJ 2587 Unique Attack 判断最小割是否唯一
    Poj 1815 Friendship 枚举+求最小割
    POJ 3308 Paratroopers 最小点权覆盖 求最小割
    1227. Rally Championship
    Etaoin Shrdlu
  • 原文地址:https://www.cnblogs.com/whatbeg/p/4047222.html
Copyright © 2011-2022 走看看