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 ...
随机推荐
- asp.net mvc 5 利用ActionFilterAttribute实现权限过滤
关于c#属性的教程:http://www.runoob.com/csharp/csharp-attribute.html 在asp.net mvc5中,可以利用ActionFilterAttribut ...
- 4C 2018 福到了
输入字符c(只含有@和空格).数字n.规模n*n的二维字符矩阵. 若倒过来的数组和原数组一样形式输出提示. 最后输出以字符c替换的字符数组. #include <bits/stdc++.h> ...
- Fiddler简介以及web抓包
Fiddler简介以及web抓包 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.Fiddler简介简单来说,Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联 ...
- 聚类kmeans算法在yolov3中的应用
yolov3 kmeans yolov3在做boundingbox预测的时候,用到了anchor boxes.这个anchors的含义即最有可能的object的width,height.事先通过聚类得 ...
- Codeforces 919 D Substring
题目描述 You are given a graph with nn nodes and mm directed edges. One lowercase letter is assigned to ...
- 转:java中的事件监听是怎样实现随时监听的
http://blog.csdn.net/qq369201191/article/details/51204006
- webservice测试窗体只能用于来自本地计算机的请求
写在前面 在编写好webservice后,发布到iis服务器,你会发现会有这样的异常“测试窗体只能用于来自本地计算机的请求”. 解决方案 在web.config中添加以下代码即可解决问题 <we ...
- readis 内部数据结构
与其他key-value数据库不同之处 不仅支持字符串值,还支持 字符串 set,get 列表 lpush,rpush,lrange 哈希 hset,hget,hgetall hmset,hmget ...
- Context都没弄明白,还怎么做Android开发?
Activity mActivity =new Activity() 作为Android开发者,不知道你有没有思考过这个问题,Activity可以new吗?Android的应用程序开发采用JAVA语言 ...
- 想给自己的实景三维模型做个案例集?Wish3D Earth再合适不过了
很多朋友向用户展示实景三维模型的时候经常面临这样的问题: