1752. [BOI2007]摩基亚Mokia
★★★ 输入文件:mokia.in
输出文件:mokia.out
简单对比
时间限制:5 s 内存限制:128 MB
【题目描述】
摩尔瓦多的移动电话公司摩基亚(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
【数据规模】
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
解题:CDQ分治
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 300010; 4 struct QU { 5 int x1,x2,y,f,id; 6 bool operator<(const QU &t) const { 7 return y == t.y?id < t.id:y < t.y; 8 } 9 } A[maxn<<1],B[maxn<<1],Q[maxn<<1]; 10 int C[maxn<<1],Li[maxn<<1],ans[maxn<<1],tot,cnt,ask; 11 void add(int i,int val) { 12 for(; i < maxn; i += i&(-i)) C[i] += val; 13 } 14 int sum(int i) { 15 int ret = 0; 16 for(; i > 0; i -= i&(-i)) ret += C[i]; 17 return ret; 18 } 19 void cdq(int L,int R) { 20 if(R <= L) return; 21 int mid = (L + R)>>1; 22 cdq(L,mid); 23 cdq(mid + 1,R); 24 int a = 0,b = 0,j = 0; 25 for(int i = L; i <= mid; ++i) 26 if(Q[i].id == -1) A[a++] = Q[i]; 27 for(int i = mid+1; i <= R; ++i) 28 if(Q[i].id != -1) B[b++] = Q[i]; 29 sort(A,A + a); 30 sort(B,B + b); 31 for(int i = 0; i < b; ++i) { 32 for(; j < a && A[j].y <= B[i].y; ++j) add(A[j].x1,A[j].f); 33 ans[B[i].id] += B[i].f*sum(B[i].x2); 34 ans[B[i].id] -= B[i].f*sum(B[i].x1); 35 } 36 for(int i = 0; i < j; ++i) 37 add(A[i].x1,-A[i].f); 38 } 39 int main() { 40 int n,op; 41 freopen ( "mokia.in", "r", stdin ) ; 42 freopen ( "mokia.out", "w", stdout ) ; 43 while(~scanf("%*d%d",&n)) { 44 memset(C,0,sizeof C); 45 memset(ans,0,sizeof ans); 46 tot = cnt = ask = 0; 47 while(scanf("%d",&op),op < 3) { 48 if(op == 1) { 49 scanf("%d%d%d",&Q[cnt].x1,&Q[cnt].y,&Q[cnt].f); 50 Li[tot++] = Q[cnt].x1; 51 Q[cnt++].id = -1; 52 } else if(op == 2) { 53 scanf("%d%d%d%d",&Q[cnt].x1,&Q[cnt+1].y,&Q[cnt+1].x2,&Q[cnt].y); 54 Li[tot++] = Q[cnt].x1-1; 55 Li[tot++] = Q[cnt+1].x2; 56 --Q[cnt+1].y; 57 Q[cnt].x2 = Q[cnt+1].x2; 58 Q[cnt+1].x1 = Q[cnt].x1; 59 Q[cnt].id = Q[cnt+1].id = ask++; 60 Q[cnt++].f = 1; 61 Q[cnt++].f = -1; 62 } 63 } 64 sort(Li,Li + tot); 65 tot = unique(Li,Li + tot) - Li; 66 for(int i = 0; i < cnt; ++i) { 67 if(Q[i].id == -1) Q[i].x1 = lower_bound(Li,Li + tot,Q[i].x1) - Li + 1; 68 else { 69 Q[i].x1 = lower_bound(Li,Li + tot,Q[i].x1 - 1) - Li + 1; 70 Q[i].x2 = lower_bound(Li,Li + tot,Q[i].x2) - Li + 1; 71 } 72 } 73 cdq(0,cnt-1); 74 for(int i = 0; i < ask; ++i) 75 printf("%d ",ans[i]); 76 } 77 return 0; 78 }