照例先上题面
1752. [BOI2007]摩基亚Mokia
输入文件:mokia.in 输出文件:mokia.out
时间限制:1.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
【提示】
输入
输出
意义
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
一句话题意:维护一个W*W的矩阵,初始值均为0.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.
看到题之后第一眼我们或许会考虑二维树状数组,但是后来我们发现这个蜜汁数据范围刚好卡掉了$O((M+Q)*log^2W)$的二维树状数组...
然后我们注意到题目没有要求强制在线,所以我们可以考虑CDQ分治来解决这个问题.
CDQ分治的详解我打算放在下一篇博文w所以在这里先不详细解释了QwQ
作为CDQ分治的裸题我就直接贴袋马了憋打我(逃
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 7 const int MAXW=2000010; 8 const int MAXA=800010; 9 10 struct Node{ 11 int x; 12 int y; 13 int ID; 14 int value; 15 int position; 16 int operation; 17 bool operator<(const Node& x)const{ 18 if(this->x==x.x&&this->y==x.y) 19 return this->operation<x.operation; 20 else 21 return this->x==x.x?this->y<x.y:this->x<x.x; 22 } 23 }; 24 Node query[MAXA]; 25 Node tmp[MAXA]; 26 27 int n; 28 int m; 29 int cnt; 30 int c[MAXW]; 31 int ans[MAXA]; 32 33 int Query(int); 34 int LowBit(int); 35 void Add(int,int); 36 void FastRead(int&); 37 void CDQ(int,int); 38 39 int main(){ 40 #ifndef ASC_LOCAL 41 freopen("mokia.in","r",stdin); 42 freopen("mokia.out","w",stdout); 43 #endif 44 int operation; 45 FastRead(n); 46 FastRead(n); 47 while(true){ 48 FastRead(operation); 49 if(operation==1){ 50 ++m; 51 FastRead(query[m].x); 52 FastRead(query[m].y); 53 FastRead(query[m].value); 54 query[m].operation=0; 55 } 56 else if(operation==2){ 57 int x1,x2,y1,y2; 58 cnt++; 59 FastRead(x1); 60 FastRead(y1); 61 FastRead(x2); 62 FastRead(y2); 63 query[++m].position=cnt; 64 query[m].x=x1-1; 65 query[m].y=y1-1; 66 query[m].value=1; 67 query[m].operation=1; 68 69 query[++m].position=cnt; 70 query[m].x=x2; 71 query[m].y=y2; 72 query[m].value=1; 73 query[m].operation=1; 74 75 query[++m].position=cnt; 76 query[m].x=x1-1; 77 query[m].y=y2; 78 query[m].value=-1; 79 query[m].operation=1; 80 81 query[++m].position=cnt; 82 query[m].x=x2; 83 query[m].y=y1-1; 84 query[m].value=-1; 85 query[m].operation=1; 86 } 87 else break; 88 } 89 for(int i=1;i<=m;i++) 90 query[i].ID=i; 91 std::sort(query+1,query+m+1); 92 CDQ(1,m); 93 for(int i=1;i<=cnt;i++) 94 printf("%d ",ans[i]); 95 return 0; 96 } 97 98 void CDQ(int l,int r){ 99 if(l==r) 100 return; 101 int mid=(l+r)>>1; 102 int ll=l; 103 int lr=mid+1; 104 for(int i=l;i<=r;i++){ 105 if(query[i].ID<=mid&&query[i].operation==0) 106 Add(query[i].y,query[i].value); 107 if(query[i].ID>mid&&query[i].operation==1) 108 ans[query[i].position]+=query[i].value*Query(query[i].y); 109 } 110 for(int i=l;i<=r;i++){ 111 if(query[i].ID<=mid&&query[i].operation==0) 112 Add(query[i].y,-query[i].value); 113 } 114 for(int i=l;i<=r;i++){ 115 if(query[i].ID<=mid) 116 tmp[ll++]=query[i]; 117 else 118 tmp[lr++]=query[i]; 119 } 120 for(int i=l;i<=r;i++) 121 query[i]=tmp[i]; 122 CDQ(l,mid); 123 CDQ(mid+1,r); 124 } 125 126 inline int Query(int x){ 127 int ans=0; 128 for(;x>0;x-=LowBit(x)){ 129 ans+=c[x]; 130 } 131 return ans; 132 } 133 134 inline void Add(int x,int d){ 135 for(;x<=n;x+=LowBit(x)){ 136 c[x]+=d; 137 } 138 } 139 140 inline int LowBit(int x){ 141 return x&-x; 142 } 143 144 void FastRead(int& target){ 145 target=0; 146 register char ch=getchar(); 147 while(!isdigit(ch)&&ch!=EOF) 148 ch=getchar(); 149 while(isdigit(ch)){ 150 target=target*10+ch-'0'; 151 ch=getchar(); 152 } 153 }
扔个图就跑