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 ...
随机推荐
- hdu 4994(博弈)
Revenge of Nim Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- LeetCode OJ-- Merge k Sorted Lists *@
https://oj.leetcode.com/problems/merge-k-sorted-lists/ 这道题主要是考虑测试数据的特点吧. 刚开始的时候想,每次找出头结点中最小的两个,然后取最小 ...
- Android Studio查看其它APP的布局结构
概述 日常使用别家的APP过程中,会遇到一些比较好看的布局,这时候我们就想学习一下别人的布局结构,以便参考. (1)手机连接电脑.设置手机为USB调试模式 (2)运行Android Studio,打开 ...
- 误加all_load引起的程序报错
一.为什么要加-all_load 在64位的mac系统和iOS系统下,链接器有一个bug,会导致只包含有类别的静态库无法使用-ObjC标志来加载文件.解决方法是使用-all_load或者-force_ ...
- Codeforces Gym101522 D.Distribution of Days-算日期 (La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017)
D.Distribution of Days The Gregorian calendar is internationally the most widely used civil calendar ...
- python调用phantomjs组件(windows和linux)
phantomjs在windows和linux系统,可以通selenium的webdriver直接调用,所以只要将phantomjs程序加载到python程序目录下. 示例代码如下所示: #建立Pha ...
- Linux(三) 一些命令
系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...
- Jsp2.0自定义标签(第二天)——自定义循环标签
今天是学习自定义标签的第二天,主要是写一个自定义的循环标签. 先看效果图: 前台页面Jsp代码 <%@ page language="java" contentType=&q ...
- python logging模块学习(转)
前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...
- 给java类加static修饰编译器会说什么?
Illegal modifier for the class XXX;only public abstract & final are permitted.