洛谷 P4390 [BOI2007]Mokia 摩基亚 解题报告
P4390 [BOI2007]Mokia 摩基亚
题目描述
摩尔瓦多的移动电话公司摩基亚(\(Mokia\))设计出了一种新的用户定位系统。和其他的定位系统一样,它能够迅速回答任何形如“用户\(C\)的位置在哪?”的问题,精确到毫米。但其真正高科技之处在于,它能够回答形如“给定区域内有多少名用户?”的问题。
在定位系统中,世界被认为是一个\(W\times W\)的正方形区域,由\(1\times1\)的方格组成。每个方格都有一个坐标\((x,y)\),\(1\le x,y\le W\)。坐标的编号从\(1\)开始。对于一个\(4\times4\)的正方形,就有\(1\le x\le 4,1\le y\le 4\)(如图):
请帮助\(Mokia\)公司编写一个程序来计算在某个矩形区域内有多少名用户。
输入输出格式
输入格式:
有三种命令,意义如下:
命令 参数 意义
0 W初始化一个全零矩阵。本命令仅开始时出现一次。1 x y A向方格\((x,y)\)中添加\(A\)个用户。\(A\)是正整数。2 X1 Y1 X2 Y2查询\(X_1\le x\le X_2,Y_1\le y\le Y_2\)所规定的矩形中的用户数量3无参数 结束程序。本命令仅结束时出现一次。
输出格式:
对所有命令\(2\),输出一个一行整数,即当前询问矩形内的用户数量。
说明
对于所有数据:
\(1\le W\le 2000000\)
\(1\le X_1\le X_2\le W\)
\(1\le Y_1\le Y_2\le W\)
\(1\le x,y\le W\)
\(0<A\le 10000\)
命令\(1\)不超过\(160000\)个。
命令\(2\)不超过\(10000\)个。
之前做了个园丁的题目,是所有询问在修改之后的。
于是直接把四维偏序的一维搞成区间操作\(O(n\log^2n)\)水过去了。
然后这个题就萎掉了,想了一会儿还是三个\(\log\),于是打算拿树套树水过去。
结果套的线段树\(MLE\)了,无语...
然后看了看正解,发现直接对矩形容斥就可以了。
就是把一个矩形\((a,b),(c,d)\)拆成\((1,1),(a-1,b-1)\)、\((1,1),(a-1,d)\)、\((1,1),(c,b-1)\)、\((1,1),(c,d)\)四个做。
然后就又成了三维偏序...
Code:
#include <cstdio>
#include <algorithm>
const int N=2e5+10;
int n,m,k,op,ans[N],s[N<<2],dx[N<<2],cntx,dy[N<<2],cnty;
void add(int x,int d){while(x<=cnty)s[x]+=d,x+=x&-x;}
int ask(int x){int sum=0;while(x)sum+=s[x],x-=x&-x;return sum;}
struct node
{
int a,b,c,op;
bool friend operator <(node n1,node n2)
{
return n1.a==n2.a?n1.op<n2.op:n1.a<n2.a;
}
}q[N],qs[N];
void CDQ(int l,int r)
{
if(l==r) return;
int mid=l+r>>1;
CDQ(l,mid),CDQ(mid+1,r);
int lp=l,rp=mid+1,loc=l-1;
while(lp<=mid&&rp<=r)
{
if(q[lp]<q[rp])
{
if(!q[lp].op) add(q[lp].b,q[lp].c);
qs[++loc]=q[lp++];
}
else
{
if(q[rp].op) ans[q[rp].op]+=q[rp].c*ask(q[rp].b);
qs[++loc]=q[rp++];
}
}
while(rp<=r)
{
if(q[rp].op) ans[q[rp].op]+=q[rp].c*ask(q[rp].b);
qs[++loc]=q[rp++];
}
for(int i=l;i<lp;i++) if(!q[i].op) add(q[i].b,-q[i].c);
while(lp<=mid) qs[++loc]=q[lp++];
for(int i=l;i<=r;i++) q[i]=qs[i];
}
int main()
{
scanf("%d%d",&n,&n);
scanf("%d",&op);int a,b,c,d;
while(op!=3)
{
if(op==1)
{
++m;
scanf("%d%d%d",&q[m].a,&q[m].b,&q[m].c);
dx[++cntx]=q[m].a,dy[++cnty]=q[m].b;
}
else
{
scanf("%d%d%d%d",&a,&b,&c,&d);
dx[++cntx]=a-1,dy[++cnty]=b-1,dx[++cntx]=c,dy[++cnty]=d;
++k;
q[++m]={a-1,b-1,1,k};
q[++m]={a-1,d,-1,k};
q[++m]={c,b-1,-1,k};
q[++m]={c,d,1,k};
}
scanf("%d",&op);
}
std::sort(dx+1,dx+1+cntx);
std::sort(dy+1,dy+1+cnty);
cntx=std::unique(dx+1,dx+1+cntx)-dx-1;
cnty=std::unique(dy+1,dy+1+cnty)-dy-1;
for(int i=1;i<=m;i++)
{
q[i].a=std::lower_bound(dx+1,dx+1+cntx,q[i].a)-dx;
q[i].b=std::lower_bound(dy+1,dy+1+cnty,q[i].b)-dy;
}
CDQ(1,m);
for(int i=1;i<=k;i++) printf("%d\n",ans[i]);
return 0;
}
2018.11.27
洛谷 P4390 [BOI2007]Mokia 摩基亚 解题报告的更多相关文章
- [洛谷P4390][BOI2007]Mokia 摩基亚
题目大意: 维护一个W*W的矩阵,每次操作可以增加某格子的权值,或询问某子矩阵的总权值. 题解:CDQ分治,把询问拆成四个小矩形 卡点:无 C++ Code: #include <cstdio& ...
- P4390 [BOI2007]Mokia 摩基亚 (CDQ解决三维偏序问题)
题目描述 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如"用户C的位置在哪?"的问题,精确到毫米.但其真正高科 ...
- Luogu P4390 [BOI2007]Mokia 摩基亚 | CDQ分治
题目链接 $CDQ$分治. 考虑此时在区间$[l,r]$中,要计算$[l,mid]$中的操作对$[mid+1,r]$中的询问的影响. 计算时,排序加上树状数组即可. 然后再递归处理$[l,mid]$和 ...
- P4390 [BOI2007]Mokia 摩基亚(cdq分治)
一样是cdq的板子 照着园丁的烦恼就好了 代码 #include <cstdio> #include <cstring> #include <algorithm> ...
- P4390 [BOI2007]Mokia 摩基亚
传送门 对于一个询问 $(xa,ya),(xb,yb)$,拆成 $4$ 个询问并容斥一下 具体就是把询问变成求小于等于 $xb,yb$ 的点数,减去小于等于 $xa-1,yb$ 和小于等于 $xb,y ...
- 【BZOJ1176】[BOI2007]Mokia 摩基亚
[BZOJ1176][BOI2007]Mokia 摩基亚 题面 bzoj 洛谷 题解 显然的\(CDQ\)\(/\)树套树题 然而根本不想写树套树,那就用\(CDQ\)吧... 考虑到点\((x1,y ...
- [BOI2007]Mokia 摩基亚
Description: 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如"用户C的位置在哪?"的问题,精确到毫 ...
- cogs1752[boi2007]mokia 摩基亚 (cdq分治)
[题目描述] 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米.但其真正高科技之处在于,它能 ...
- 【cdq分治】【P4390】[BOI2007]Mokia 摩基亚
Description 给你一个 \(W~\times~W\) 的矩阵,每个点有权值,每次进行单点修改或者求某子矩阵内权值和,允许离线 Input 第一行是两个数字 \(0\) 和矩阵大小 \(W\) ...
随机推荐
- HCIE理论-IPV6
ipv4与ipv6的对比 IPv4 :32 bit 点分十进制 192.168.1.1 2^32=42.9亿 ipv4地址不足IPv6 :128 bit 十六进制 2^128 冒号分十六进制ipv4 ...
- ubuntu apt-xxx
1. apt-get install xxx 2. dpkg -l ; list software already installed. 3. apt-cache dumpavail ; print ...
- 关于js回调方法 js递归时使用方法
js中递归调用本身可以这样: function a1(n){ a1(n)}但是如果需要在参数n进行自增的情况下判断会出错: function a1(n){ if(n>10) return 'aa ...
- mybatis按datetime条件查询,参数为时间戳时
mybatis按datetime条件查询,参数为时间戳时,如果数据库为2018-1-1 20:22:10, 你的时间戳也为2018-1-1 20:22:10,但却没找到数据.可能是时差导致的.百度修正 ...
- vue的ui库使用Element UI,纯html页面,不使用webpack那玩意
使用手册访问:https://cloud.tencent.com/developer/doc/1270 第一步:在head添加样式 <link rel="stylesheet" ...
- 自动化运维工具saltstack01 -- 之SaltStack介绍、安装与基础使用
SaltStack介绍 官网地址:http://www.saltstack.com 官方文档地址:http://docs.saltstack.com Github:http://Github.com/ ...
- 算法笔记(c++)--c++中碰到的一些用法
算法笔记(c++)--c++中碰到的一些用法 toupper(xxx)可以变成大写; tolower(xx)小写 isalpha(xxx)判断是不是字母 isalnum(xx)判断是不是数字 abs( ...
- Github三次学习
作者声明:本文参照aicoder.com马伦老师的文档,根据自己的学习情况而做的笔记,仅供交流学习. Git入门到高级教程 为什么要进行项目文件的版本管理 代码备份和恢复 团队开发和协作流程 项目分支 ...
- Python 变量和常量及数据类型
一.变量的命名 变量由字母.数字和下划线组成.变量的第1个字符必须是字母或下划线. 二.变量的赋值 例: x = 1 三.局部变量 局部变量只能在函数或者代码段内使用. 四.全局变量 在函数之外定义的 ...
- 使用C和C++实现“电梯”的区别
C 面向过程: 该电梯不允许未卜先知,故程序需逐条处理乘客请求并更新当前各变量状态. 如何获得最短时间:是否立即响应请求,计算出不同决策下的总时间,并进行比较,然后选择最短时间 ...