【题目描述】

摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统。和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米。但其真正高科技之处在于,它能够回答形如“给定区域内有多少名用户?”的问题。

在定位系统中,世界被认为是一个W×W的正方形区域,由1×1的方格组成。每个方格都有一个坐标(x,y),1<=x,y<=W。坐标的编号从1开始。对于一个4×4的正方形,就有1<=x<=4,1<=y<=4(如图):

请帮助Mokia公司编写一个程序来计算在某个矩形区域内有多少名用户。

【输入格式】

有三种命令,意义如下:

命令 参数 意义
0 W 初始化一个全零矩阵。本命令仅开始时出现一次。
1 x y A 向方格(x,y)中添加A个用户。A是正整数。
2 X1 Y1 X2 Y2 查询X1<=x<=X2,Y1<=y<=Y2所规定的矩形中的用户数量
3 无参数 结束程序。本命令仅结束时出现一次。

【输出格式】

对所有命令2,输出一个一行整数,即当前询问矩形内的用户数量。

【输入样例】

0 4

1 2 3 3

2 1 1 3 3

1 2 2 2

2 2 2 3 4

3

【输出样例】

3

5

【提示】

输入 输出 意义
0 4   大小为4×4的全零正方形
1 2 3 3   向(2,3)方格加入3名用户
2 1 1 3 3   查询矩形1<=x<=3,1<=y<=3内的用户数量
  3 查询结果
1 2 2 2   向(2,2)方格加入2名用户
2 2 2 3 4   查询矩形2<=x<=3,2<=y<=4内的用户数量
  5 查询结果
3   终止程序

【数据规模】

1<=W<=2000000

1<=X1<=X2<=W

1<=Y1<=Y2<=W

1<=x,y<=W

0<A<=10000

命令1不超过160000个。

命令2不超过10000个。

【来源】

Balkan Olypiad in Informatics 2007,Mokia

Solution

cdq分支模板题

#include <stdio.h>
#include <algorithm>
int w, C[2000010], ans[10010];
struct Que{
int x, y, v, tp, _id;
}q[200010];
bool cmp(Que a, Que b) {return a.x < b.x;}
inline void add(int i, int d){
for(; i <= w; i += i & (-i))
C[i] += d;
}
inline int sum(int i){
int res = 0;
for(; i; i -= i & (-i))
res += C[i];
return res;
}
void cdq(int l, int r){
if(l == r) return;
int mid = l + r >> 1;
cdq(l, mid), cdq(mid + 1, r);
std::sort(q + l, q + mid + 1, cmp);
std::sort(q + mid + 1, q + r + 1, cmp);
int j = l;
for(int i = mid + 1; i <= r; i++){
for(; j <= mid && q[j].x <= q[i].x; j++)
if(q[j].tp == 1) add(q[j].y, q[j].v);
if(q[i].tp == 2) ans[q[i]._id] += q[i].v * sum(q[i].y);
}
for(int i = l; i < j; i++)
if(q[i].tp == 1) add(q[i].y, -q[i].v);
}
int main(){
int op, a, b, c, d, id = 0, tot = 0;
freopen("mokia.in", "r", stdin), freopen("mokia.out", "w", stdout);
while(scanf("%d", &op) && op != 3){
if(op == 0)
scanf("%d", &w);
else if(op == 1){
scanf("%d%d%d", &a, &b, &c);
q[++id] = (Que) {a, b, c, 1, 0};
}
else{
++tot;
scanf("%d%d%d%d", &a, &b, &c, &d);
q[++id] = (Que) {a - 1, b - 1, 1, 2, tot};
q[++id] = (Que) {c, d, 1, 2, tot};
q[++id] = (Que) {a - 1, d, -1, 2, tot};
q[++id] = (Que) {c, b - 1, -1, 2, tot};
}
}
cdq(1, id);
for(int i = 1; i <= tot; i++)
printf("%d\n", ans[i]);
fclose(stdin), fclose(stdout);
return 0;
}

  

最新文章

  1. ORACLE 利用 REPLACE函数替换字段字符串
  2. C/C++中const的用法 分类: C/C++ 2015-07-05 00:43 85人阅读 评论(0) 收藏
  3. AVAudioPlayer播放并实现了后台播放和远程控制
  4. Cocos Code IDE新建lua工程报错解决方案
  5. c#中的事件
  6. localStorage和sessionStorage区别
  7. 发布自己的nuget包;报错source parameter was not specified
  8. 【转载】为什么CPU有多层缓存
  9. How to do Mathematics
  10. html5生成柱状图(条形图)
  11. 14.6.7 Configuring the Number of Background InnoDB IO Threads 配置InnoDB IO Threads的数量
  12. QT程序启动界面的使用
  13. WinForm常用代码
  14. poj2914无向图的最小割模板
  15. [Essay] Apache Flink:十分可靠,一分不差
  16. jquery fileupload
  17. 【bzoj3039】玉蟾宫 悬线法
  18. Icons - Material Design各种ICON图标大全
  19. HTML和SEO基础知识:H标签全透视
  20. CSS中字体响应式的设置

热门文章

  1. Android属性动画ObjectAnimator的使用1
  2. set和get方法
  3. 1-最全CSS3选择器
  4. VS打包后生成快捷方式:目标指向错误、Icon图标分辨率有误问题解决方案
  5. Web常见几种攻击与预防方式
  6. AJPFX关于构造器的总结
  7. 解决webstromm标签高亮问题
  8. android ListView 分析(一)
  9. 面向对象编程(OOP)基础知识(一)
  10. vscode配置python环境