BZOJ 4066: 简单题

4066: 简单题

Time Limit: 50 Sec  Memory Limit: 20 MB
Submit: 2373  Solved: 622
[Submit][Status][Discuss]

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:

 

命令

参数限制

内容

1 x y A

1<=x,y<=N,A是正整数

将格子x,y里的数字加上A

2 x1 y1 x2 y2

1<=x1<= x2<=N

1<=y1<= y2<=N

输出x1 y1 x2 y2这个矩形内的数字和

3

终止程序

 
 

 

Input

输入文件第一行一个正整数N。
接下来每行一个操作。每条命令除第一个数字之外,
均要异或上一次输出的答案last_ans,初始时last_ans=0。
 

 

Output

对于每个2操作,输出一个对应的答案。

 

Sample Input

4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3

Sample Output

3
5

HINT

 

数据规模和约定

1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。

样例解释见OJ2683

 

新加数据一组,但未重测----2015.05.24

 

 

 

Source

[Submit][Status][Discuss]

 

记得BZOJ还有两道题和这个题是一个意思,但是略有不同。

 

这道题有两个地方需要注意:

1. 数据通过一定方式强制在线

2. 内存限制只有20M,二维数据结构基本被终结

 

显然是KD-Tree了,而且需要定期重建以保持其优秀的性质。看到有的题解没有重建就AC了,大概新加数据有卡这类程序,亦或者是大佬的KD-Tree十分优美吧,我等蒟蒻并无此功底……

 

因为数据以3作为输入终止信号,一开始并不知道有多少操作,也不知道操作是什么,我也懒得先存起来统计操作次数,所以需要找一个合适的重建限度,及进行多少次插入操作后,重建整个KD-Tree。要来数据在本地试了几个数字,发现这个限度取1500~2000较为合适(我一开始猜了个500,直接TLE了),虽然OJ和本地的测试环境有些差距吧,但还是可以作为参考,小伙伴可以像我一样取1700,OJ上跑了30S。

 

  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 inline int getint(void)
  5 {
  6     int r = 0, f = 0, c = getchar();
  7 
  8     for (; c < 48; c = getchar())
  9         if (c == '-')f ^= 1;
 10     
 11     for (; c > 47; c = getchar())
 12         r = r * 10 + c - 48;
 13     
 14     return f ? -r : r;
 15 }
 16 
 17 const int siz = 200005;
 18 
 19 struct node
 20 {
 21     int val;
 22     int sum;
 23     int pos[2];
 24     int son[2];
 25     int mini[2];
 26     int maxi[2];
 27 
 28     inline void setup(int x, int y, int v)
 29     {
 30         val = sum = v;
 31         son[0] = son[1] = 0;
 32         pos[0] = mini[0] = maxi[0] = x;
 33         pos[1] = mini[1] = maxi[1] = y;
 34     }
 35 }tr[siz]; int tot;
 36 
 37 inline void update(int t)
 38 {
 39     tr[t].sum = tr[t].val;
 40 
 41     if (tr[t].son[0])
 42         tr[t].sum += tr[tr[t].son[0]].sum;
 43     if (tr[t].son[1])
 44         tr[t].sum += tr[tr[t].son[1]].sum;
 45 
 46     tr[t].mini[0] = tr[t].maxi[0] = tr[t].pos[0];
 47     tr[t].mini[1] = tr[t].maxi[1] = tr[t].pos[1];
 48 
 49     for (int i = 0; i < 2; ++i)if (tr[t].son[i])
 50         for (int j = 0; j < 2; ++j)
 51         {
 52             if (tr[t].mini[j] > tr[tr[t].son[i]].mini[j])
 53                 tr[t].mini[j] = tr[tr[t].son[i]].mini[j];
 54             if (tr[t].maxi[j] < tr[tr[t].son[i]].maxi[j])
 55                 tr[t].maxi[j] = tr[tr[t].son[i]].maxi[j];
 56         }
 57 }
 58 
 59 void insert(int &t, int p, int k)
 60 {
 61     if (!t)t = p;
 62     else
 63     {
 64         if (tr[p].pos[k] <= tr[t].pos[k])
 65             insert(tr[t].son[0], p, k ^ 1);
 66         else 
 67             insert(tr[t].son[1], p, k ^ 1);
 68         
 69         update(t);
 70     }
 71 }
 72 
 73 int cmpk;
 74 
 75 inline bool cmp(const node &a, const node &b)
 76 {
 77     if (a.pos[cmpk] != b.pos[cmpk])
 78         return a.pos[cmpk] < b.pos[cmpk];
 79     else
 80         return a.pos[cmpk^1] < b.pos[cmpk^1];
 81 }
 82 
 83 int build(int l, int r, int k)
 84 {
 85     int mid = (l + r) >> 1; cmpk = k;
 86     
 87     std::nth_element(tr + l, tr + mid, tr + r + 1, cmp);
 88     
 89     tr[mid].son[0] = l < mid ? build(l, mid - 1, k ^ 1) : 0;
 90     tr[mid].son[1] = r > mid ? build(mid + 1, r, k ^ 1) : 0;
 91     
 92     return update(mid), mid;
 93 }
 94 
 95 int x1, y1, x2, y2, ans;
 96 
 97 inline bool none(int t)
 98 {
 99     return 
100         x1 > tr[t].maxi[0]
101     ||  x2 < tr[t].mini[0]
102     ||  y1 > tr[t].maxi[1]
103     ||  y2 < tr[t].mini[1];
104 }
105 
106 inline bool have(int t)
107 {
108     return 
109         x1 <= tr[t].mini[0]
110     &&  x2 >= tr[t].maxi[0]
111     &&  y1 <= tr[t].mini[1]
112     &&  y2 >= tr[t].maxi[1];
113 }
114 
115 inline bool in(int t)
116 {
117     return
118         x1 <= tr[t].pos[0]
119     &&  x2 >= tr[t].pos[0]
120     &&  y1 <= tr[t].pos[1]
121     &&  y2 >= tr[t].pos[1];
122 }
123 
124 void query(int t)
125 {
126     if (none(t))return;
127     if (have(t))ans += tr[t].sum;
128     else
129     {
130         if (in(t))ans += tr[t].val;
131         if (tr[t].son[0])query(tr[t].son[0]);
132         if (tr[t].son[1])query(tr[t].son[1]);
133     }
134 }
135 
136 signed main(void)
137 {
138 //    freopen("simple.in", "r", stdin);
139 //    freopen("simple.out", "w", stdout); 
140     
141     int n = getint(), root = ++tot;
142 
143     tr[root].setup(n >> 1, n >> 1, 0);
144 
145     while (true)
146     {
147         int k = getint();
148 
149         if (k == 1)
150         {
151             int x = getint() ^ ans;
152             int y = getint() ^ ans;
153             int v = getint() ^ ans;
154             
155             tr[++tot].setup(x, y, v);
156             
157             if (tot % 1700)
158                 insert(root, tot, 0);
159             else
160                 root = build(1, tot, 0);
161         }
162         else if (k == 2)
163         {
164             x1 = getint() ^ ans;
165             y1 = getint() ^ ans;
166             x2 = getint() ^ ans;
167             y2 = getint() ^ ans;
168             
169             ans = 0; query(root);
170 
171             printf("%d\n", ans);
172         }
173         else break;
174     }
175     
176 //    fclose(stdin);
177 //    fclose(stdout);
178 }
179 
180 /*
181 2000 : 18.02
182 1800 : 17.22
183 1700 : 16.89
184 1500 : 17.74
185 1000 : 20.80
186 900  : 22.53
187 700  : 25.08
188 500  : 33.55
189 300  : T L E
190 */

 

@Author: YouSiki

posted @ 2017-01-14 15:48  YouSiki  阅读(417)  评论(4编辑  收藏  举报