POJ 1195 2维线段树(树套树实现) 树状数组

   1:  #include <stdio.h>
   2:  #include <string.h>
   3:  #include <stdlib.h>
   4:  #include <algorithm>
   5:  #include <iostream>
   6:  using namespace std;
   7:   
   8:  #define LL(a)   a<<1
   9:  #define RR(a)   a<<1|1
  10:  const int MaxL = 1005;
  11:  struct sub_Seg_tree_node
  12:  {
  13:      int subleft,subright; // ydown = subleft, yup = subright
  14:  //    int maxval;  // the maval of the rect x [left,right], y [subleft, subright]
  15:      int sum;     // the sum of the num of point in rect x [left, right], y [subleft, subright]
  16:  };
  17:   
  18:  struct Seg_tree_node
  19:  {
  20:      int left,right;       // left = xleft, right = xright
  21:      sub_Seg_tree_node T[MaxL<<2];
  22:  } TT[MaxL<<2];
  23:   
  24:  void sub_build(int subl, int subr, int subidx, int idx)
  25:  {
  26:      TT[idx].T[subidx].subleft=subl;
  27:      TT[idx].T[subidx].subright=subr;
  28:  //    TT[idx].T[subidx].maxval=-1;
  29:      TT[idx].T[subidx].sum=0;
  30:      if(subl==subr)  return;
  31:      int mid=(subl+subr)>>1;
  32:      sub_build(subl, mid, LL(subidx), idx);
  33:      sub_build(mid+1, subr, RR(subidx), idx);
  34:  }
  35:   
  36:  void build(int l, int r, int subl, int subr, int idx)
  37:  {
  38:      TT[idx].left = l, TT[idx].right = r;
  39:      sub_build(subl, subr, 1, idx);
  40:      if(l==r) return;
  41:      int mid=(l+r)>>1;
  42:      build(l,mid,subl,subr, LL(idx));
  43:      build(mid+1,r,subl,subr, RR(idx));
  44:  }
  45:   
  46:  void sub_update(int y, int val, int subidx, int idx)
  47:  {
  48:      TT[idx].T[subidx].sum += val;
  49:  //    TT[idx].T[subidx].maxval=max(TT[idx].T[subidx].maxval, val);
  50:      if(TT[idx].T[subidx].subleft == TT[idx].T[subidx].subright) return;
  51:      int mid=(TT[idx].T[subidx].subleft+TT[idx].T[subidx].subright)>>1;
  52:      if(y <= mid)
  53:          sub_update(y, val, LL(subidx), idx);
  54:      else
  55:          sub_update(y, val, RR(subidx), idx);
  56:  }
  57:   
  58:  void update(int x, int y, int val, int idx)
  59:  {
  60:      sub_update(y, val, 1, idx);
  61:      if(TT[idx].left == TT[idx].right) return;
  62:      int mid=(TT[idx].left+TT[idx].right)>>1;
  63:      if( x<=mid)
  64:          update(x,y,val, LL(idx) );
  65:      else
  66:          update(x,y, val,RR(idx));
  67:  }
  68:   
  69:  //int sub_query(int subl, int subr, int subidx, int idx)
  70:  //{
  71:  //    if(TT[idx].T[subidx].subleft == subl && TT[idx].T[subidx].subright == subr)
  72:  //        return TT[idx].T[subidx].maxval;
  73:  //    int mid = (TT[idx].T[subidx].subleft + TT[idx].T[subidx].subright)>>1;
  74:  //    if(subr <= mid)
  75:  //        return sub_query(subl, subr, LL(subidx), idx);
  76:  //    else if(subl > mid)
  77:  //        return sub_query(subl, subr, RR(subidx), idx);
  78:  //    else
  79:  //        return max(sub_query(subl, mid, LL(subidx), idx),sub_query(mid+1, subr, RR(subidx), idx));
  80:  //}
  81:  //
  82:  //int query(int l, int r, int subl, int subr, int idx)
  83:  //{
  84:  //    if(TT[idx].left == l && TT[idx].right == r)
  85:  //        return sub_query(subl, subr, 1, idx);
  86:  //    int mid = (TT[idx].left + TT[idx].right)>>1;
  87:  //    if(r <= mid)
  88:  //        return query(l,r, subl,subr, LL(idx));
  89:  //    else if(l > mid)
  90:  //        return query(l, r, subl, subr, RR(idx));
  91:  //    else
  92:  //        return max(query(l, mid, subl, subr, LL(idx)),query(mid+1, r, subl,subr, RR(idx)));
  93:  //}
  94:   
  95:  int sub_query(int subl, int subr, int subidx, int idx)
  96:  {
  97:      if(TT[idx].T[subidx].subleft == subl && TT[idx].T[subidx].subright == subr)
  98:          return TT[idx].T[subidx].sum;
  99:      int mid = (TT[idx].T[subidx].subleft + TT[idx].T[subidx].subright)>>1;
 100:      if(subr <= mid)
 101:          return sub_query(subl, subr, LL(subidx), idx);
 102:      else if(subl > mid)
 103:          return sub_query(subl, subr, RR(subidx), idx);
 104:      else
 105:          return sub_query(subl, mid, LL(subidx), idx) + sub_query(mid+1, subr, RR(subidx), idx);
 106:  }
 107:   
 108:  int query(int l, int r, int subl, int subr, int idx)
 109:  {
 110:      if(TT[idx].left == l && TT[idx].right == r)
 111:          return sub_query(subl, subr, 1, idx);
 112:      int mid = (TT[idx].left + TT[idx].right)>>1;
 113:      if(r <= mid)
 114:          return query(l,r, subl,subr, LL(idx));
 115:      else if(l > mid)
 116:          return query(l, r, subl, subr, RR(idx));
 117:      else
 118:          return query(l, mid, subl, subr, LL(idx))+ query(mid+1, r, subl,subr, RR(idx));
 119:  }
 120:   
 121:  int x1[10005];
 122:  int y1[10005];
 123:  int x2[10005];
 124:  int y2[10005];
 125:  int px[10005];
 126:  int py[10005];
 127:  int pval[10005];
 128:  //
 129:  //int main()
 130:  //{
 131:  //    freopen("1.txt","r",stdin);
 132:  //    int NN,MM;
 133:  //    cin>>NN>>MM;
 134:  //
 135:  //    for(int i=0; i<NN; i++)
 136:  //        scanf("%d%d%d", &px[i],&py[i], &pval[i]);
 137:  //
 138:  //    for(int i=0; i<MM; i++)
 139:  //    {
 140:  //        scanf("%d%d%d%d", &x1[i], &y1[i], &x2[i], &y2[i]);
 141:  //        if(x1[i] > x2[i]) swap(x1[i], x2[i]);
 142:  //        if(y1[i] > y2[i]) swap(y1[i], y2[i]);
 143:  //    }
 144:  //
 145:  //    build(0, 1060, 0, 1060, 1);
 146:  //    for(int i=0; i<NN; i++)
 147:  //    {
 148:  //        cout<<"update point "<<px[i]<<" "<<py[i]<<endl;
 149:  //        update(px[i],py[i],pval[i], 1);
 150:  //    }
 151:  //
 152:  //    for(int i=0; i<MM; i++)
 153:  //    {
 154:  //        cout<<"query ret "<<x1[i]<<" "<<x2[i]<<" "<<y1[i]<<" "<<y2[i]<<endl;
 155:  //        cout<<"Ret "<<query(x1[i],x2[i],y1[i],y2[i],1)<<endl;
 156:  //    }
 157:  //
 158:  //    return 0;
 159:  //}
 160:  int s;
 161:  int main()
 162:  {
 163:  //    freopen("1.txt","r",stdin);
 164:      int i;
 165:      int sb;
 166:      int sb1,sb2,sb3,sb4;
 167:      scanf("%d",&sb);
 168:      while(sb!=3)
 169:      {
 170:          switch(sb)
 171:          {
 172:          case 0:
 173:              scanf("%d",&s);
 174:              build(0,s,0,s,1);
 175:              break;
 176:          case 1:
 177:              scanf("%d%d%d",&sb1,&sb2,&sb3);
 178:              update(sb1,sb2,sb3,1);
 179:              break;
 180:          case 2:
 181:              scanf("%d%d%d%d",&sb1,&sb2,&sb3,&sb4);
 182:              printf("%d\n",query(sb1,sb3,sb2,sb4,1));
 183:              break;
 184:          default:
 185:              goto ed;
 186:          }
 187:          scanf("%d",&sb);
 188:      }
 189:  ed:
 190:      ;
 191:      return 0;
 192:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

树状数组来做这个题目相对来说简单得多! 
树状数组则清楚得多.相对来说二维线段树用得比较少,而且功能都比较简单,查询平面矩形包含几个点,查询矩形最大值之类的.

   1:  #include <iostream>
   2:  #include <stdio.h>
   3:  #include <string.h>
   4:  using namespace std;
   5:   
   6:  #define MAX 1026
   7:  int s[MAX][MAX];
   8:  int lowbit(int x)
   9:  {
  10:      return x&(x^(x-1));
  11:  }
  12:   
  13:  int N;
  14:   
  15:  void change(int a,int b,int delta)
  16:  {
  17:      for(int x=a; x<=N; x+=lowbit(x))
  18:          for(int y=b; y<=N; y+=lowbit(y))
  19:              s[x][y]+=delta;
  20:  }
  21:  int sum(int a,int b)
  22:  {
  23:      int res=0;
  24:      for(int x=a; x>0; x-=lowbit(x))
  25:          for(int y=b; y>0; y-=lowbit(y))
  26:              res+=s[x][y];
  27:      return res;
  28:  }
  29:  int main()
  30:  {
  31:      int n;
  32:      while(cin>>n)
  33:      {
  34:          if(n==0)
  35:          {
  36:              cin>>N; N++;
  37:              memset(s,0,sizeof(s));
  38:          }
  39:          else if(n==1)
  40:          {
  41:              int a,b,c;
  42:              cin>>a>>b>>c; a++; b++;
  43:              change(a,b,c);
  44:          }
  45:          else if(n==2)
  46:          {
  47:              int a,b,c,d;
  48:              cin>>a>>b>>c>>d;
  49:              a++;b++;c++;d++;
  50:              cout<<sum(c,d) + sum(a-1,b-1) - sum(a-1,d) - sum(c,b-1)<<endl;
  51:          }
  52:          else break;;
  53:      }
  54:      return 0;
  55:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

POJ 1195 2维线段树(树套树实现) 树状数组,布布扣,bubuko.com

时间: 2024-12-08 01:14:04

POJ 1195 2维线段树(树套树实现) 树状数组的相关文章

POJ 2155 二维线段树

POJ 2155  二维线段树 思路:二维线段树就是每个节点套一棵线段树的树. 刚开始因为题目是求A[I,J],然后在y查询那直接ans^=Map[i][j]的时候没看懂,后面自己把图画出来了才理解. 因为只有0和1,所以可以用异或来搞,而不需要每次都需要修改. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #incl

POJ 2155 二维线段树 经典的记录所有修改再统一遍历 单点查询

本来是想找一个二维线段树涉及懒惰标记的,一看这个题,区间修改,单点查询,以为是懒惰标记,敲到一半发现这二维线段树就不适合懒惰标记,你更新了某段的某列,但其实其他段的相应列也要打标记,但因为区间不一样,又不好打...也可能是我这是在套用一维线段树的思想,还有更好的二维线段树懒惰标记方法 反正到现在我还没搞定二维线段树的懒惰标记,因为这道题不用懒惰标记,因为是二进制序列,区间修改仅限于翻转操作,那就只要记录每次操作,最后查询的时候从上往下把所有修改都来上一遍,就可以了.就类似于树状数组的第二种用法,

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

POJ 1195 二维树状数组

Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 18489   Accepted: 8558 Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The

POJ 2155 2维线段树 || 2维BIT

#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <map> #include <set> #include <stack> #define mp make_pair #define pa pair<int,int> #define pb p

树状数组求逆序对:POJ 2299、3067

前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换相邻的两数使它有序,要你求出交换的次数.实质上就是求逆序对,网上有很多人说它的原理是冒泡排序,可以用归并排序来求出,但我一时间想不出它是如何和归并排序搭上边的(当初排序没学好啊~),只好用刚学过的树状数组来解决了.在POJ 1990中学到了如何在实际中应用上树状数组,没错,就是用个特殊的数组来记录即

poj_1190 树状数组

题目大意 给定一个S*S的矩形,该矩形由S*S个1x1的单元格构成,每个单元格内可以放一个整数,每次有如下可能操作: (1)改变某个单位单元格中的数的大小 (2)查询由若干个连续单元格构成的X*Y的大小的矩形内所有数的总和 题目分析 典型的区间操作,而且是单点更新,区间查询.因此使用树状数组,不过应该使用二维树状数组.二维树状数组和一维其实没什么区别....     另:用线段树也做了一份,但是超时,果然树状数组在效率上还是略胜线段树的.下面给出树状数组的AC代码和线段树的TLE代码. 实现(c

【数据结构之树状数组】从零认识树状数组

一.关于树状数组 树状数组(Binary Indexed Tree,简称BIT),是一种修改和查询复杂度都为O(logN)的数据结构.但树状数组仅支持单点修改,在查询时,树状数组也要求被查询的区间具有可区间加减的性质.不过,树状数组由于代码实现容易.占用空间小,常用于代替线段树. 二.详解树状数组 在这里,我们定义原序列为a,树状数组为c,则有: 其中,k为i的二进制表示中末尾0的个数,例如:i=3(101)时,k=0:i=8(1000)时,k=3. 定义函数lowbit(x)=2k(k为x的二

poj 1195:Mobile phones(二维线段树,矩阵求和,经典题)

Mobile phones Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 14391   Accepted: 6685 Description Suppose that the fourth generation mobile phone base stations in the Tampere area operate as follows. The area is divided into squares. The