UVa 11992 (线段树 区间修改) Fast Matrix Operations

比较综合的一道题目。

二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max

写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递标记。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 const int maxnode = 1 << 17;
  7 int _sum, _min, _max, op, x1, x2, y1, y2, x, v;
  8 
  9 struct IntervalTree
 10 {
 11     int maxv[maxnode], minv[maxnode], sumv[maxnode], setv[maxnode], addv[maxnode];
 12 
 13     void maintain(int o, int L, int R)
 14     {
 15         int lc = o*2, rc = o*2+1;
 16         if(R > L)
 17         {
 18             sumv[o] = sumv[lc] + sumv[rc];
 19             minv[o] = min(minv[lc], minv[rc]);
 20             maxv[o] = max(maxv[lc], maxv[rc]);
 21         }
 22         if(setv[o] >= 0) { maxv[o] = minv[o] = setv[o]; sumv[o] = (R-L+1)*setv[o]; }
 23         if(addv[o]) { minv[o] += addv[o]; maxv[o] += addv[o]; sumv[o] += (R-L+1)*addv[o]; }
 24     }
 25 
 26     void pushdown(int o)
 27     {
 28         int lc = o*2, rc = o*2+1;
 29         if(setv[o] >= 0)
 30         {
 31             setv[lc] = setv[rc] = setv[o];
 32             addv[lc] = addv[rc] = 0;
 33             setv[o] = -1;
 34         }
 35         if(addv[o])
 36         {
 37             addv[lc] += addv[o];
 38             addv[rc] += addv[o];
 39             addv[o] = 0;
 40         }
 41     }
 42 
 43     void update(int o, int L, int R)
 44     {
 45         int lc = o*2, rc = o*2+1;
 46         if(y1 <= L && R <= y2)
 47         {
 48             if(op == 1) addv[o] += v;
 49             else { setv[o] = v; addv[o] = 0; }
 50         }
 51         else
 52         {
 53             pushdown(o);    //往下传递标记
 54             int M = (L + R) / 2;
 55             if(y1 <= M) update(lc, L, M); else maintain(lc, L, M);
 56             if(y2 > M) update(rc, M+1, R); else maintain(rc, M+1, R);
 57         }
 58         maintain(o, L, R);
 59     }
 60 
 61     void query(int o, int L, int R, int add)
 62     {
 63         if(setv[o] >= 0)
 64         {
 65             int v = setv[o] + addv[o] + add;
 66             _sum += v * (min(y2, R) - max(y1, L) + 1);
 67             _min = min(_min, v);
 68             _max = max(_max, v);
 69         }
 70         else if(y1 <= L && R <= y2)
 71         {
 72             _sum += sumv[o] + add*(R-L+1);
 73             _min = min(_min, minv[o] + add);
 74             _max = max(_max, maxv[o] + add);
 75         }
 76         else
 77         {
 78             int M = (L + R) / 2;
 79             if(y1 <= M) query(o*2, L, M, add + addv[o]);
 80             if(y2 > M) query(o*2+1, M+1, R, add + addv[o]);
 81         }
 82     }
 83 };
 84 
 85 const int maxr = 20 + 5;
 86 const int INF = 1000000000;
 87 
 88 IntervalTree tree[maxr];
 89 
 90 int main()
 91 {
 92     //freopen("in.txt", "r", stdin);
 93 
 94     int r, c, m;
 95     while(scanf("%d%d%d", &r, &c, &m) == 3)
 96     {
 97         memset(tree, 0, sizeof(tree));
 98         for(int x = 1; x <= r; x++)
 99         {
100             memset(tree[x].setv, -1, sizeof(tree[x].setv));
101             tree[x].setv[1] = 0;
102         }
103 
104         while(m--)
105         {
106             scanf("%d%d%d%d%d", &op, &x1, &y1, &x2, &y2);
107             if(op < 3)
108             {
109                 scanf("%d", &v);
110                 for(x = x1; x <= x2; x++) tree[x].update(1, 1, c);
111             }
112             else
113             {
114                 _sum = 0; _max = -INF; _min = INF;
115                 for(x = x1; x <= x2; x++) tree[x].query(1, 1, c, 0);
116                 printf("%d %d %d\n", _sum, _min, _max);
117             }
118         }
119     }
120 
121     return 0;
122 }
代码君

 

posted @ 2015-04-01 16:00  AOQNRMGYXLMV  阅读(306)  评论(0编辑  收藏  举报