洛谷P4390 [BalkanOI2007] Mokia 摩基亚 题解
题目传送门。
想必 我的另外一篇题解 已经把这道题的思路说的很清楚了,但是那道题是把所有的修改全部告诉你,然后再一个一个问你矩阵和,但是这道题他是修改中夹着询问,但是没有关系,我们照样可做。
考虑将所有询问或修改存起来,因为我的另外一篇题解的那个思路还支持修改,那我们只需要将所有修改当成那个题里的 \(n\) 个基站(有重复点不影响),将 \(p\) 全部设置为 \(0\),然后每次修改就正常修改就行,同样是整块改那个数和前缀和,散块直接改那个数,就做完了。
但这题的思维难度和代码难度远不止如此,下面说一下要改动的点:
- 这次前缀和数组就只能每个块的处理了,因为如果全部处理,修改时就会产生后面也要修改的情况,这样处理起来就比较麻烦,如果是块前缀和,就只需要对块进行暴力处理就行了。
- 对于每次修改我们要找到当前修改的这个坐标在 \(a_i\) 中的位置,这个位置是作为散块的修改位置,因为整块它预处理时使用了排序,所以还得开一个数组记录排序后原本在 \(i\) 位置的数,现在跑到哪里了。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7+5;
struct node
{
int x;
int y;
int p;
int id;
}a[N];
int cmp(node x,node y)
{
return x.x == y.x?x.y<y.y:x.x<y.x;
}
struct node1
{
int y;
int p;
int id;
}s[N],s1[N];
int sum[N];
int id[N];
int cmp1(node1 x,node1 y)
{
return x.y<y.y;
}
struct node2
{
int x1;
int y1;
int x2;
int y2;
}e[N];
struct node3
{
int opt;
int x1;
int y1;
int x2;
int y2;
}w[N];
int mpp[N];
int mppp[N];
signed main()
{
int qq = 0;
int _,__,n = 0,m = 0;
scanf("%d %d",&_,&__);
while(1)
{
int opt;
scanf("%d",&opt);
if(opt == 1)
{
int x,y,p;
scanf("%d %d %d",&x,&y,&p);
a[++n] = {x,y,0,n};
w[++qq] = {opt,x,y,p,0};
}
else if(opt == 2)
{
int x1,y1,x2,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
e[++m] = {x1,y1,x2,y2};
w[++qq] = {opt,x1,y1,x2,y2};
}
else
{
break;
}
}
int len = sqrt(n);
for(int i = 1;i<=n;i++)
{
id[i] = (i+len-1)/len;
}
sort(a+1,a+n+1,cmp);
for(int i = 1;i<=n;i++)
{
s[i].y = a[i].y;
s[i].p = a[i].p;
s[i].id = i;
s1[i] = s[i];
mpp[a[i].id] = i;
}
for(int i = 1;i<=id[n];i++)
{
int l = (i-1)*len+1,r = min(i*len,n);
sort(s1+l,s1+r+1,cmp1);
sum[l] = s1[l].p;
for(int j = l+1;j<=r;j++)
{
sum[j] = sum[j-1]+s1[i].p;
}
}
for(int i = 1;i<=n;i++)
{
mppp[s1[i].id] = i;
}
int cnt = 0;
for(int i = 1;i<=qq;i++)
{
if(w[i].opt == 1)
{
cnt++;
int tt = mpp[cnt];
int ttt = mppp[tt];
s[tt].p+=w[i].x2;
s1[ttt].p+=w[i].x2;
int l = (id[ttt]-1)*len+1,r = min(id[ttt]*len,n);
sort(s1+l,s1+r+1,cmp1);
sum[l] = s1[l].p;
for(int i = l+1;i<=r;i++)
{
sum[i] = sum[i-1]+s1[i].p;
}
}
else
{
int x1 = w[i].x1,y1 = w[i].y1,x2 = w[i].x2,y2 = w[i].y2;
int l = 1,r = n,num = 0;
while(l<=r)
{
int mid = l+r>>1;
if(a[mid].x>=x1)
{
num = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
if(!num||a[num].x>x2)
{
printf("0\n");
continue;
}
l = 1,r = n;
int num1 = 0;
while(l<=r)
{
int mid = l+r>>1;
if(a[mid].x<=x2)
{
num1 = mid;
l = mid+1;
}
else
{
r = mid-1;
}
}
if(!num1||a[num1].x<x1)
{
printf("0\n");
continue;
}
int ss = 0;
for(int i = id[num]+1;i<=id[num1]-1;i++)
{
int l = (i-1)*len+1,r = i*len,num2 = 0;
while(l<=r)
{
int mid = l+r>>1;
if(s1[mid].y>=y1)
{
num2 = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
if(!num2||s1[num2].y>y2)
{
continue;
}
l = (i-1)*len+1,r = i*len;
int num3 = 0;
while(l<=r)
{
int mid = l+r>>1;
if(s1[mid].y<=y2)
{
num3 = mid;
l = mid+1;
}
else
{
r = mid-1;
}
}
if(!num3||s1[num3].y<y1)
{
continue;
}
if(num2 == (i-1)*len+1)
{
ss+=sum[num3];
}
else
{
ss+=sum[num3]-sum[num2-1];
}
}
if(id[num] == id[num1])
{
for(int i = num;i<=num1;i++)
{
if(s[i].y>=y1&&s[i].y<=y2)
{
ss+=s[i].p;
}
}
}
else
{
for(int i = num;i<=id[num]*len;i++)
{
if(s[i].y>=y1&&s[i].y<=y2)
{
ss+=s[i].p;
}
}
for(int i = (id[num1]-1)*len+1;i<=num1;i++)
{
if(s[i].y>=y1&&s[i].y<=y2)
{
ss+=s[i].p;
}
}
}
printf("%d\n",ss);
}
}
return 0;
}
这个题还是很有难度的,如果有不会的欢迎私信提问!
洛谷P4390 [BalkanOI2007] Mokia 摩基亚 题解的更多相关文章
- 洛谷 P4390 [BOI2007]Mokia 摩基亚 解题报告
P4390 [BOI2007]Mokia 摩基亚 题目描述 摩尔瓦多的移动电话公司摩基亚(\(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\) ...
随机推荐
- 中电金信:GienTech动态|中标、入选、参会...近期精彩呈现!
中电金信参编业内首个银行核心系统分级度量标准 2024年6月6日,由中国信息通信研究院云计算与大数据研究所主办的"应用现代化赋能银行核心系统升级"交流会议在京召开.会议发布了业内首 ...
- 基于SpringMVC XML配置文件的Dubbo开发与使用
[模块一] 首先引入Dubbo的依赖资源,这里我们使用基于SpringMVC的项目于Dubbo进行整合 先进行依赖导入. pom.xml <!--zookeeper--> ...
- 【bug记录】AttributeError: 'CollectReport' object has no attribute 'description'
问题截图 问题原因 有完全重复用例,因为写用例的时候,为了图方便,直接复制的,还没来得及改,然后,用pytest运行的时候,就报这个错误了. 问题解决 去掉重复就行了
- 龙哥量化:MACD指标的金叉死叉,这样使用更准确(图解)
如果您需要代写技术指标公式, 请联系我. 龙哥QQ:591438821 龙哥微信:Long622889 本文的策略过于简单,你可以加一些更复杂的限制条件 1.水上金叉,可看涨; 2.水上死叉,是洗盘; ...
- 波折重重:Linux实时系统Xenomai宕机问题的深度定位
目录 一 前言 二 背景 三 原因分析及措施 硬件原因 应用软件 操作系统 四 分析定位 转机 拨云见雾 irq计数 Schedstat coreclk 现象结论 五 原因一 六 原因二 七 解决 八 ...
- Qt编写物联网管理平台(支持win/linux/mac/嵌入式linux/modbus等)
一.前言 这个物联网综合管理平台前后迭代了五年,一点一滴慢慢积累起来,从最开始的只有modbus串口协议解析以及简单的表格显示数据,慢慢的逐渐增加了tcp_rtu支持,用户管理模块,地图监控模块,而后 ...
- 清除 TortoiseSVN已存储的连接URL地址
Eclipse 清除 SVN 的 URL 历史记录1.关闭 Eclipse2.进入 工程目录 \.metadata\.plugins\org.tigris.subversion.subclipse.c ...
- 即时通讯技术文集(第35期):IM群聊技术合集(Part2) [共12篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第35 期. [- 1 -] 直播系统聊天技术(一):百万在线的美拍直播弹幕系统的实时推送技术 ...
- dotnet最小webApi开发实践
dotnet最小webApi开发实践 软件开发过程中,经常需要写一些功能验证代码.通常是创建一个console程序来验证测试,但黑呼呼的方脑袋界面,实在是不讨人喜欢. Web开发目前已是网络世界中的主 ...
- Rust远程加载shellcode
学习rust, 练习写一个loader, 不足之处还请指教 编写 隐藏黑框 在注释掉所有打印语句后编译运行还是会弹黑框, 解决方法是头部添加一行(指定 Rust 编译器生成的可执行文件为 Window ...