hdu 4819 2013 Asia Regional Changchun G (四叉树|| 二维线段树单点更新 模板题)

http://acm.hdu.edu.cn/showproblem.php?pid=4819

题意:

给你一个n*n的矩阵, 每个点是一个数字, Q个操作,每次选择一个子矩阵, 把中心元素替换成子矩阵中最大值和最小值之和的二分之一。

思路:

显然是一个二维线段树…..

然而菜鸡如我,并没有写过二维线段树啊?

那怎么办呢

一首《凉凉》送给自己

然而我们还有四叉树2333

2A,写错一个地方。第一次写四叉树,orz

  1#include <bits/stdc++.h>
  2#define ms(a,x) memset(a,x,sizeof(a))
  3#define lowbit(x) (x&(-x))
  4using namespace std;
  5typedef long long LL;
  6const double eps = 1e-8;
  7const double PI = acos(-1.0);
  8const int N=805;
  9int n;
 10int a[N][N];
 11struct Tree
 12{
 13    int mn,mx;
 14    Tree()
 15    {
 16        mn = 1E9;
 17        mx = 0;
 18    }
 19    void init()
 20    {
 21        mn = 1E9;
 22        mx = 0;
 23    }
 24}tree[N*10000];
 25int _max( int a,int b,int c,int d)
 26{
 27    int ret = max(a,b);
 28    ret = max(ret,c);
 29    ret = max(ret,d);
 30    return ret;
 31}
 32int _min( int a,int b,int c,int d)
 33{
 34    int ret = min(a,b);
 35    ret = min(ret,c);
 36    ret = min(ret,d);
 37    return ret;
 38}
 39void PushUp( int rt)
 40{
 41//  cout<<"rt:"<<rt<<endl;
 42    tree[rt].mn = _min(tree[rt*4+1].mn,tree[rt*4+2].mn,tree[rt*4+3].mn,tree[rt*4+4].mn);
 43    tree[rt].mx = _max(tree[rt*4+1].mx,tree[rt*4+2].mx,tree[rt*4+3].mx,tree[rt*4+4].mx);
 44}
 45
 46
 47void insert( int idx,int lx,int rx,int ly,int ry,int X,int Y,int val)
 48{
 49//  cout<<"val:"<<val<<endl;
 50    if (lx==rx&&ly==ry)
 51    {
 52        tree[idx].mn = tree[idx].mx = val;
 53//      cout<<"fuck"<<" val:"<<val<<" mn:"<<tree[idx].mn <<" mx:"<<tree[idx];
 54        return;
 55    }
 56    int mx = (lx+rx) >> 1;
 57    int my = (ly+ry) >> 1;
 58    if (X<=mx&&Y<=my) insert(idx*4+1,lx,mx,ly,my,X,Y,val);
 59    if (X<=mx&&Y>=my+1) insert(idx*4+2,lx,mx,my+1,ry,X,Y,val);
 60    if (X>=mx+1&&Y<=my) insert(idx*4+3,mx+1,rx,ly,my,X,Y,val);
 61    if (X>=mx+1&&Y>=my+1) insert(idx*4+4,mx+1,rx,my+1,ry,X,Y,val);
 62//  puts("miao");
 63    PushUp(idx);
 64}
 65int queryMN( int idx,int lx,int rx,int ly,int ry,int Lx,int Rx,int Ly,int Ry)
 66{
 67    if (Lx<=lx && Rx>=rx && Ly<=ly && Ry>=ry) return tree[idx].mn;
 68    int mx = (lx+rx)>>1,my = (ly+ry)>>1,t=1E9;
 69    if (Lx<=mx && Ly<=my)  t = min(t,queryMN(idx*4+1,lx,mx,ly,my,Lx,Rx,Ly,Ry));
 70    if (Lx<=mx && Ry>my) t = min(t,queryMN(idx*4+2,lx,mx,my+1,ry,Lx,Rx,Ly,Ry));
 71    if (Rx>mx  && Ly<=my) t = min (t,queryMN(idx*4+3,mx+1,rx,ly,my,Lx,Rx,Ly,Ry)); 
 72    if (Rx>mx&&Ry>my) t = min (t,queryMN(idx*4+4,mx+1,rx,my+1,ry,Lx,Rx,Ly,Ry));
 73    return t;
 74}
 75int queryMX( int idx,int lx,int rx,int ly,int ry,int Lx,int Rx,int Ly,int Ry)
 76{
 77    if (Lx<=lx && Rx>=rx && Ly<=ly && Ry>=ry) return tree[idx].mx;
 78    int mx = (lx+rx)>>1,my = (ly+ry)>>1,t=0;
 79    if (Lx<=mx && Ly<=my)  t = max(t,queryMX(idx*4+1,lx,mx,ly,my,Lx,Rx,Ly,Ry));
 80    if (Lx<=mx && Ry>my) t = max(t,queryMX(idx*4+2,lx,mx,my+1,ry,Lx,Rx,Ly,Ry));
 81    if (Rx>mx  && Ly<=my) t = max (t,queryMX(idx*4+3,mx+1,rx,ly,my,Lx,Rx,Ly,Ry)); 
 82    if (Rx>mx&&Ry>my) t = max(t,queryMX(idx*4+4,mx+1,rx,my+1,ry,Lx,Rx,Ly,Ry));
 83    return t;
 84}
 85void init()
 86{
 87    for ( int i = 0 ; i < 8E6 ; i++) tree[i].init();
 88}
 89int main(){
 90#ifdef YourCodeHasBug
 91//  freopen("in2","r",stdin);
 92#endif
 93    int T;
 94    cin>>T;
 95    int cas = 0 ;
 96    while (T--)
 97    {
 98        init();
 99        scanf("%d",&n);
100        for ( int i = 1 ; i <= n ; i++)
101            for ( int j = 1 ; j <= n ; j++)
102            {
103                scanf("%d",&a[i][j]);
104//              cout<<"a[i][j]:"<<a[i][j]<<endl;
105                insert(0,1,n,1,n,i,j,a[i][j]);
106            }
107//      for ( int i = 0 ; i <= 20 ; i++) printf("tree_mn:%d mx:%d\n",tree[i].mn,tree[i].mx);
108        int m;
109        scanf("%d",&m);
110            printf("Case #%d:\n",++cas);
111        while (m--)
112        {
113            int x,y,L;
114            scanf("%d %d %d",&x,&y,&L);
115            int Lx = max(x-L/2,1);
116            int Rx = min(n,x+L/2);
117            int Ly = max(y-L/2,1);
118            int Ry = min(n,y+L/2);
119//          printf("x:[%d,%d] y:[%d,%d]\n",Lx,Rx,Ly,Ry);
120            int mn = queryMN(0,1,n,1,n,Lx,Rx,Ly,Ry);
121            int mx = queryMX(0,1,n,1,n,Lx,Rx,Ly,Ry);
122            int newval = floor((mn+mx)/2);
123            //printf("mn:%d mx:%d %d\n",mn,mx,newval);
124            printf("%d\n",newval);
125            insert(0,1,n,1,n,x,y,newval);
126        }
127    }
128#ifdef YourCodeHasBug
129    fclose(stdin);
130#endif
131    return 0;
132}

然后又写了一个二维线段树的版本,借鉴了kuangbin的写法,改成了自己习惯的代码风格。

果然常数差好多。。。(据说是因为四叉树退化得厉害QAQ

第三个是四叉树的做法,第二个是kuangbin 的 树套树版本的二维线段树

第一个是我改写kuangbin代码之后的代码。

可以看出,四叉树虽然好写好理解一点,但是时间上不太优秀啊….

  1/* ***********************************************
  2Author :111qqz
  3Created Time :2017年11月10日 星期五 17时18分40秒
  4File Name :4819_2D.cpp
  5 ************************************************ */
  6
  7#include <bits/stdc++.h>
  8#define PB push_back
  9#define fst first
 10#define sec second
 11#define lson l,m,rt<<1
 12#define rson m+1,r,rt<<1|1
 13#define ms(a,x) memset(a,x,sizeof(a))
 14typedef long long LL;
 15#define pi pair < int ,int >
 16#define MP make_pair
 17
 18using namespace std;
 19const double eps = 1E-8;
 20const int dx4[4]={1,0,0,-1};
 21const int dy4[4]={0,-1,1,0};
 22const int inf = 0x3f3f3f3f;
 23const int N=803;
 24struct Treey
 25{
 26    int l,r;
 27    int Max,Min;
 28};
 29int n;
 30int rtx[N],rty[N] ; //rtx[i]表示横坐标为i的点属于哪棵线段树
 31struct  Treex
 32{
 33    int l,r;
 34    Treey treey[N<<2];
 35    void build ( int _l,int _r,int rt)
 36    {
 37    treey[rt].l = _l;
 38    treey[rt].r = _r;
 39    treey[rt].Max = -inf;
 40    treey[rt].Min = inf;
 41    if (_l==_r)
 42    {
 43        rty[_l] = rt;
 44        return;
 45    }
 46    int m = (_l + _r) / 2;
 47    build (_l,m,rt<<1);
 48    build(m+1,_r,rt<<1|1);
 49    }
 50    int QMin( int L,int R,int rt)
 51    {
 52    if (treey[rt].l >= L && treey[rt].r <= R) return treey[rt].Min;
 53    int m = (treey[rt].l + treey[rt].r) / 2;
 54    int ret = 1E9;
 55    if (L<=m) ret = QMin(L,R,rt<<1);
 56    if (R>=m+1) ret = min(ret,QMin(L,R,rt<<1|1));
 57    return ret;
 58    }
 59    int QMax( int L,int R,int rt)
 60    {
 61    if (treey[rt].l >= L && treey[rt].r <= R) return treey[rt].Max;
 62    int m = (treey[rt].l + treey[rt].r) / 2;
 63    int ret = 0 ;
 64    if (L<=m) ret = QMax (L,R,rt<<1);
 65    if (R>=m+1) ret = max(ret,QMax(L,R,rt<<1|1));
 66    return ret;
 67    }
 68}treex[N<<2];
 69
 70void build (int l,int r,int rt)
 71{
 72    treex[rt].l = l;
 73    treex[rt].r = r;
 74    treex[rt].build(1,n,1);
 75    if (l==r)
 76    {
 77    rtx[l] = rt;
 78    return;
 79    }
 80    int m = (l+r)>>1;
 81    build (lson);
 82    build (rson);
 83}
 84void update ( int x,int y,int val) //单点更新,更新a[x,y]到val
 85{
 86    int rx = rtx[x];
 87    int ry = rty[y];
 88    treex[rx].treey[ry].Min = treex[rx].treey[ry].Max = val;
 89    for ( int i = rx ; i ; i >>=1)
 90    for ( int j = ry ; j ; j >>=1)
 91    {
 92        if (i==rx && j==ry) continue; //上面更新过了
 93        if (j==ry)
 94        {
 95        treex[i].treey[j].Min = min(treex[i<<1].treey[j].Min,treex[i<<1|1].treey[j].Min);
 96        treex[i].treey[j].Max = max(treex[i<<1].treey[j].Max,treex[i<<1|1].treey[j].Max);
 97        }
 98        else
 99        {
100            treex[i].treey[j].Min = min(treex[i].treey[j<<1].Min,treex[i].treey[j<<1|1].Min);
101        treex[i].treey[j].Max = max(treex[i].treey[j<<1].Max,treex[i].treey[j<<1|1].Max);
102        }
103    }
104}
105int QMin( int L1,int R1,int L2,int R2,int rt)
106{
107    if (treex[rt].l >= L1 && treex[rt].r <= R1) return treex[rt].QMin(L2,R2,1);
108    int m = (treex[rt].l + treex[rt].r)/2;
109    int ret = 1E9;
110    if (L1<=m) ret = QMin(L1,R1,L2,R2,rt<<1);
111    if (R1>=m+1) ret = min(ret,QMin(L1,R1,L2,R2,rt<<1|1));
112    return ret;
113}
114int QMax ( int L1,int R1,int L2,int R2,int rt)
115{
116 //   printf("rt:%d l:%d r:%d  L1:%d R1:%d \n",rt,treex[rt].l,treex[rt].r,L1,R1);
117    if (treex[rt].l >= L1 && treex[rt].r <=R1) return treex[rt].QMax(L2,R2,1);
118    int m = (treex[rt].l + treex[rt].r) / 2;
119    int ret = 0 ;
120    if (L1<=m) ret = QMax(L1,R1,L2,R2,rt<<1);
121    if (R1>=m+1) ret = max(ret, QMax(L1,R1,L2,R2,rt<<1|1));
122    return ret;
123}
124
125int main() 
126{
127#ifndef  ONLINE_JUDGE 
128    freopen("./in.txt","r",stdin);
129#endif
130    int T,cas=0;
131    cin>>T;
132    while (T--)
133    {
134    printf("Case #%d:\n",++cas);
135    scanf("%d",&n);
136    build (1,n,1);
137    for ( int i = 1 ; i  <= n ; i++)
138        for ( int j = 1; j <= n ; j++)
139        {
140        int x;
141        scanf("%d",&x);
142        update(i,j,x);
143        }
144    int q;
145    scanf("%d",&q);
146    while (q--)
147    {
148        int x,y,L;
149        scanf("%d %d %d",&x,&y,&L);
150        int L1 = max(x-L/2,1);
151        int R1 = min(x+L/2,n);
152        int L2 = max(y-L/2,1);
153        int R2 = min(y+L/2,n);
154//      printf("[%d,%d] [%d,%d]\n",L1,R1,L2,R2);
155        int Mx = QMax(L1,R1,L2,R2,1);
156        int Mn = QMin(L1,R1,L2,R2,1);
157        int val = floor((Mx+Mn)/2);
158        printf("%d\n",val);
159        update(x,y,val);
160    }
161    }   
162#ifndef ONLINE_JUDGE  
163    fclose(stdin);
164#endif
165    return 0;
166}