COGS1752. [BOI2007]摩基亚Mokia
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
【提示】
| 输入 | 输出 | 意义 |
| 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
算法分析:
这个问题是 IOI 2000 Mobile 的加强版: Mobile 中 W≤1000, 就可以利用二树
状数组在 O(log 2 2 n)的时间复杂度内维护出操作 1)和操作 2). 这个问题中 W 很大,
开二维树状数组 O(W 2 )的空间显然吃不消,考虑使用动态空间的线段树,最多可
能达到操作次数 * (log 2 W) 2 个节点, 也相当大了. 考虑使用分治思想来解决问题:
将操作 1)和操作 2)按顺序看成是一个个事件,假设共有 Tot 个事件,
Tot≤170000.类似例题一,我们定义 Solve(l, r)表示对于每一个 Query 操作的事
件 i, 将 l ..i-1 的 Add 操作的所有属于 i 的矩形范围内的数值累加进来.目标是
Solve(1, n).
假设计算 Solve(L, R),递归 Solve(L, Mid),Solve(Mid + 1, r)后,对 L .. Mid
的所有 Add 操作的数值累加到 Mid + 1 .. R 的所有匹配的 Query 操作的矩形中.
后面这个问题等价于:平面中有 p 个点,q 个矩形,每个点有一个权值,求
每个矩形内的点的权值之和. 这个问题只需要对所有的点以及矩形的左右边界进
行排序,用一维树状数组或线段树在 O((p+q)log 2 W)的时间复杂度即可维护得出.
因此问题的总的时间复杂度为 O(Tot*log 2 Tot*log 2 W),不会高于二维线段树的
O(Tot*log 2 W*log 2 W)的时间复杂度.
上述这个算法无论是编程复杂度还是空间复杂度都比使用二维线段树优秀,
分治思想又一次得到了很好的应用.在这个问题中,利用分治思想我们将一个在
线维护的问题转化成一个离线问题, 将二维线段树解决的问题 降维用一维线段树
来解决,使得问题变得更加简单.
——引自《从《Cash》谈一类分治算法的应用cdq》
==============================================
哔哩吧啦,讲了一大片。
不知道你们听懂了吗?反正我是没听懂。
但这并不妨碍我们A掉这道题。
一句话概括CDQ分治思想:整体考虑[l,mid]对[mid+1,r]的影响
整体二分递归调用时,mid前的区间对mid后的区间会产生有且仅有一次影响,不重不漏。(可能描述不太准确)
还有一点,cdq分治思想主要体现在将 不断变化的决策转化成一个不变的决策集合, 将在线转化为离线
然后……还是看代码吧。(because不太好描述)
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=4e5+;
struct node{
int x1,x2,y,f,id;
node(){}
node(int x1,int x2,int y,int f,int id):x1(x1),x2(x2),y(y),f(f),id(id){}
bool operator <(const node &a)const{
if(y!=a.y) return y<a.y;
return id<a.id;
}
}q[N],s1[N],s2[N];
int m,id_cnt,cnt,BIT[N],a[N],ans[N];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline int hash(int x,int l=,int r=cnt){
while(l<r){
int mid=l+r>>;
if(x<=a[mid]) r=mid;
else l=mid+;
}
return l;
}
inline int lowbit(int x){
return x&-x;
}
inline void updata(int x,int v){
for(int i=x;i<=cnt;i+=lowbit(i)) BIT[i]+=v;
}
inline int Sum(int x){
int res=;
for(int i=x;i;i-=lowbit(i)) res+=BIT[i];
return res;
}
void CDQ(int l,int r){
if(l>=r) return ;
int mid=l+r>>,top1=,top2=,j=;
CDQ(l,mid);CDQ(mid+,r);
for(int i=l;i<=mid;i++) if(!q[i].id) s1[top1++]=q[i];
for(int i=mid+;i<=r;i++) if(q[i].id) s2[top2++]=q[i];
sort(s1,s1+top1);sort(s2,s2+top2);
//相当于把y1-y2压成一条直线,这样相当于区间[x1,x2],用一维bit维护即可
for(int i=;i<top2;i++){
for(;j<top1&&s1[j].y<=s2[i].y;j++)
updata(s1[j].x1,s1[j].f);
ans[s2[i].id]+=s2[i].f*Sum(s2[i].x2);
ans[s2[i].id]-=s2[i].f*Sum(s2[i].x1-);
}
for(int i=;i<j;i++) updata(s1[i].x1,-s1[i].f);
}
int main(){
freopen("mokia.in","r",stdin);
freopen("mokia.out","w",stdout);
int opt=read(),n=read();
for(int x1,y1,x2,y2,v;(opt=read())!=;){
if(opt&){
x1=read();y1=read();v=read();
q[++m]=node(x1,x1,y1,v,);a[m]=x1;
}
else{
x1=read();y1=read();
x2=read();y2=read();
q[++m]=node(x1,x2,y2,,++id_cnt);a[m]=x2;
q[++m]=node(x1,x2,y1-,-,id_cnt);a[m]=x1-;
}
}
sort(a+,a+m+);
cnt=unique(a+,a+m+)-(a+);
for(int i=;i<=m;i++){
if(!q[i].id) q[i].x1=hash(q[i].x1);
else q[i].x1=hash(q[i].x1-)+,q[i].x2=hash(q[i].x2);
}
CDQ(,m);
for(int i=;i<=id_cnt;i++) printf("%d\n",ans[i]);
return ;
}
UPD.2017-05-05
#include<cstdio>
#include<cstring>
#include<iostream>
#define lowbit(x) (x&-x)
using namespace std;
inline void read(int &x){
register char ch=getchar();x=;
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
}
const int N=2e5+;
struct query{
int x,y,d,id;
query(){}
query(int _x,int _y,int _d){
x=_x,y=_y,d=_d;
}
}q[N],a[N];int m,n,ans[N];
struct BIT{
int c[(int)2e6+];
inline void clr(){memset(c,,sizeof c);}
inline void plus(int &p,int v){
for(int i=p;i<=n;i+=lowbit(i)) c[i]+=v;
}
inline int qsum(int &p){
int res=;
for(int i=p;i;i-=lowbit(i)) res+=c[i];
return res;
}
}bit;
bool operator <(const query &a,const query &b){
return a.x!=b.x?a.x<b.x:
a.y!=b.y?a.y<b.y:
a.d>b.d;
}
void CDQ(int l,int r){
if(l==r) return ;
int mid=(l+r)>>;
CDQ(l,mid);CDQ(mid+,r);
int p0=l,p1=mid+;
for(int i=l;i<=r;i++){
a[i]=q[(p1>r||p0<=mid&&q[p0]<q[p1]?p0:p1)++];
if(a[i].d&&a[i].id<=mid) bit.plus(a[i].y,a[i].d);
if(!a[i].d&&a[i].id>mid) ans[a[i].id]+=bit.qsum(a[i].y);
}
for(int i=l;i<=r;i++){
if(a[i].d&&a[i].id<=mid) bit.plus(a[i].y,-a[i].d);
q[i]=a[i];
}
}
int main(){
freopen("mokia.in","r",stdin);
freopen("mokia.out","w",stdout);
read(n);read(n);
for(int op,x,y,x0,y0;read(op),op<;){
read(x);read(y);read(x0);
if(op&){
q[++m]=query(x,y,x0);
ans[m]=-;
}
else{
read(y0);
q[++m]=query(x0,y0,);
q[++m]=query(x-,y0,);
q[++m]=query(x0,y-,);
q[++m]=query(x-,y-,);
}
}
for(int i=;i<=m;i++) q[i].id=i;
CDQ(,m);
for(int i=;i<=m;i++) if(~ans[i]){
printf("%d\n",ans[i]-ans[i+]-ans[i+]+ans[i+]);i+=;
}
return ;
}
COGS1752. [BOI2007]摩基亚Mokia的更多相关文章
- COGS1752 [BOI2007]摩基亚Mokia(CDQ分治 + 二维前缀和 + 线段树)
题目这么说的: 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它 ...
- COGS1752. [BOI2007]摩基亚Mokia(CDQ,树状数组)
题目描述 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它能够回 ...
- COGS1752. [BOI2007]摩基亚Mokia CDQ
CDQ的板子题 #include<cstdio> #include<cstring> #include<iostream> #include<algorith ...
- COJS 1752. [BOI2007]摩基亚Mokia
1752. [BOI2007]摩基亚Mokia ★★★ 输入文件:mokia.in 输出文件:mokia.out 简单对比时间限制:5 s 内存限制:128 MB [题目描述] 摩尔瓦 ...
- 分治(CDQ):[BOI2007]摩基亚Mokia
[题目描述] 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它能 ...
- 【COGS1752】 BOI2007—摩基亚Mokia
http://cogs.pro/cogs/problem/problem.php?pid=1752 (题目链接) 题意 给出$n*n$的棋盘,单点修改,矩阵查询. Solution 离线以后CDQ分治 ...
- Bzoj1176:Mokia&Cogs1752:[BOI2007]摩基亚Mokia
题目 Cogs 没有Bzoj的权限号 Sol 离线,\(CDQ\)分治,把询问拆成\(4\)个,变成每次求二位前缀和 那么只要一个修改操作(关键字为时间,\(x\),\(y\))都在这个询问前,就可以 ...
- [COGS 1752] 摩基亚Mokia
照例先上题面 1752. [BOI2007]摩基亚Mokia 输入文件:mokia.in 输出文件:mokia.out 时间限制:1.5 s 内存限制:128 MB [题目描述] 摩尔瓦多的移 ...
- [BOI2007]摩基亚
题目:洛谷P4390.BZOJ1176. 题目大意: 给你一个\(W\times W\)的矩阵,初始每个数都为\(S\).现在有若干操作: 1. 给某个格子加上一个值:2. 询问某个子矩阵的值的和:3 ...
随机推荐
- LeetCode OJ-- 3Sum Closest
https://oj.leetcode.com/problems/3sum-closest/ 给一列数和target,在这一列数中找出3个数,使其和最接近target,返回这个target. 一般思路 ...
- AC日记——Oulipo poj 3461
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37958 Accepted: 15282 Description The ...
- Educational Codeforces Round 39 (Rated for Div. 2) B. Weird Subtraction Process[数论/欧几里得算法]
https://zh.wikipedia.org/wiki/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95 取模也是一样的,就当多减几次. 在欧几里得最初的 ...
- Codeforces 903F Clear The Matrix(状态压缩DP)
题目链接 Clear The Matrix 题意 给定一个$4 * n$的矩形,里面的元素为$'.'$或$'*'$.现在有$4$种正方形可以覆盖掉$'*'$,正方形的边长分别为$1,2,3,4$. 求 ...
- 10.1综合强化刷题 Day7
noip提高组模拟赛 ...
- facebook architecture 2 【转】
At the scale that Facebook operates, a lot of traditional approaches to serving web content breaks d ...
- UVA - 11774 Doom's Day
看样例猜结论hhhhhh,竟然蒙对了..(正确性待证明) #include<bits/stdc++.h> #define ll long long using namespace std; ...
- STM32命名
STM32产品命名 示例: STM32 F 100 C 6 T 6 B XXX 1 2 3 4 5 6 7 8 9 从上面的料号可以看出以下信息: ST品牌ARM Cortex-Mx系列内核32位超值 ...
- 【音乐App】—— Vue-music 项目学习笔记:歌手详情页开发
前言:以下内容均为学习慕课网高级实战课程的实践爬坑笔记. 项目github地址:https://github.com/66Web/ljq_vue_music,欢迎Star. 歌曲列表 歌曲播放 一.子 ...
- vue.js+koa2项目实战(五)axios 及 vue2.0 子组件和父组件之间的传值
axios 用法: 1.安装 npm install axios --save-dev 2.导入 import axios from 'axios'; 3.使用 axios.post(url,para ...