[COGS 1752] 摩基亚Mokia

照例先上题面

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分治的裸题我就直接贴袋马了憋打我(

GitHub

  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\n",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 }
Backup

扔个图就跑

 

posted @ 2017-07-20 19:19  rvalue  阅读(240)  评论(0编辑  收藏  举报