洛谷P4169 天使玩偶 CDQ分治
还是照着CDQ的思路来。
但是有一些改动:
- 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的。怎么办?旋转!做4次就好了。
- 统计的不是和,而是——max!理由如下:
设当前点是(x,y),目标点是(x',y'),那么所求的|x-x'|+|y-y'|首先用旋转大法化为x-x'+y-y',然后我们发现这个东西其实就是x+y-x'-y'=(x+y)-(x'+y'),而x+y我们是已知的。所以我们求一下max(x'+y')即可。具体实现是对树状数组魔改。
然后交上去发现狂T不止...
疯狂优化!首先把树状数组的max从作死的M改成了所有坐标中最大的mm,发现不行,跑去看题解。
发现不能每次sort,而且还要删点。
然后学习了一波操作之后,成功的到达了91分...还是有3个点死活过不了。把题解拿下来一交,发现居然也T了一个点,哈哈哈。
听从雨菲的建议,果断开O2,A了。
看代码理解删点优化和魔改树状数组。
// luogu-judger-enable-o2
#include <cstdio>
#include <algorithm>
using namespace std;
const int M = ,N = ,INF=0x3f3f3f3f;
inline int read()
{
int ans=;char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
return ans;
}
inline int lowbit(int x){return x&(-x);}
int ta[M+],n,mm,ans[N];int p,rx,ry;
inline void add(int x,int a)
{
if(x<=) return;
for(int i=x;i<=ry;i+=lowbit(i)) ta[i]=max(ta[i],a);
return;
}
inline int getsum(int x)
{
if(x<=)return ;int ans=-INF;
for(int i=x;i>;i-=lowbit(i)) ans=max(ans,ta[i]);
return ans;
}
inline void del(int x)
{
if(x<=) return;
for(int i=x;i<=ry;i+=lowbit(i)) ta[i]=-INF;
return;
}
struct Node
{
int x,y,k=-INF,t,type;
}node[N],temp[N],f[N];
inline bool cmp_t(Node a,Node b){return a.t<b.t;}
inline void rotate()
{
for(int i=;i<=n;i++)
{
int t=f[i].x;
f[i].x=mm-f[i].y;
f[i].y=t;
}
return;
}
void CDQ(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>;
CDQ(l,mid);CDQ(mid+,r);
int i=l,j=mid+,t=;
while(i<=mid||j<=r)
{
if(j>r||(i<=mid&&node[i].x<=node[j].x))
{
if(node[i].type==) add(node[i].y,node[i].x+node[i].y);
temp[++t]=node[i++];
}
else
{
if(node[j].type>) {node[j].k=max(node[j].k,getsum(node[j].y));
ans[node[j].t]=min(ans[node[j].t],node[j].x+node[j].y-node[j].k);}
///if(node[j].type>1) node[j].k=min(node[j].k,(node[j].x+node[j].y-getsum(node[j].y)));
temp[++t]=node[j++];
}
}
t=;
for(j=l;j<i;j++) if(node[j].type==) del(node[j].y);
for(i=l;i<=r;i++) node[i]=temp[++t];
return;
} inline void Delete()
{
rx=ry=p=;
for(int i=;i<=n;i++) if(f[i].type==) rx=max(rx,f[i].x),ry=max(ry,f[i].y);
for(int i=;i<=n;i++) if(f[i].x<=rx&&f[i].y<=ry) node[++p]=f[i];
return;
}
int main()
{
fill(ta,ta+M,-INF);
int n2=read(),n3=read(),x,y,flag;
for(int i=;i<=n2;i++)
{
x=read()+;y=read()+;
f[++n].x=x;
f[n].y=y;
f[n].type=;
f[n].t=n;
mm=max(mm,x);
mm=max(mm,y);
}
for(int i=;i<=n3;i++)
{
flag=read();x=read()+;y=read()+;
f[++n].x=x;
f[n].y=y;
f[n].type=flag;
f[n].t=n;
mm=max(mm,x);
mm=max(mm,y);
}
mm++;
fill(ans+,ans+n+,INF);
for(y=;y<=;y++)
{
Delete();
ry++;
//for(int i=1;i<=p;i++) printf("%d %d %d\n",node[i].type,node[i].x,node[i].y);
CDQ(,p);
//for(int i=1;i<=n;i++)if(f[i].type==2)printf("%d ",ans[i]);
//printf("\n");
rotate();
} for(int i=;i<=n;i++)
{
if(f[i].type==) printf("%d\n",ans[i]);
} return ;
}
/**
1 3
3 1
2 5 5
1 6 4
2 5 5
*/
伪AC代码:
洛谷P4169 天使玩偶 CDQ分治的更多相关文章
- [BZOJ2716] [Violet 3]天使玩偶(CDQ分治)
[BZOJ2716] [Violet 3]天使玩偶(CDQ分治) 题面 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里, ...
- BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )
先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...
- 洛谷P3810 陌上花开(CDQ分治)
洛谷P3810 陌上花开 传送门 题解: CDQ分治模板题. 一维排序,二维归并,三维树状数组. 核心思想是分治,即计算左边区间对右边区间的影响. 代码如下: #include <bits/st ...
- [bzoj] 2716 天使玩偶 || CDQ分治
原题 已知n个点有天使玩偶,有m次操作: 操作1:想起来某个位置有一个天使玩偶 操作2:询问离当前点最近的天使玩偶的曼哈顿距离 显然的CDQ问题,三维分别为时间,x轴,y轴. 但是这道题的问题在于最近 ...
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
题目大意:初始给定平面上的一个点集.提供两种操作: 1.将一个点增加点集 2.查询距离一个点最小的曼哈顿距离 K-D树是啥...不会写... 我仅仅会CDQ分治 对于一个询问,查询的点与这个点的位置关 ...
- CH 4701 - 天使玩偶 - [CDQ分治]
题目链接:传送门 关于CDQ分治(参考李煜东<算法竞赛进阶指南>): 对于一系列操作,其中的任何一个询问操作,其结果必然等价于:初始值 + 此前所有的修改操作产生的影响. 假设共有 $m$ ...
- 天使玩偶:CDQ分治
这道好(du)题(liu)还是很不错的 挺锻炼代码能力和不断优化 卡常的能力的. 对于 每次询问 我都可以将其分出方向 然后 写 也就是针对于4个方向 左下 左上 右下 右上 这样的话 就成功转换了问 ...
- BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)
题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...
- [bzoj] 3263 陌上花开 洛谷 P3810 三维偏序|| CDQ分治 && CDQ分治讲解
原题 定义一个点比另一个点大为当且仅当这个点的三个值分别大于等于另一个点的三个值.每比一个点大就为加一等级,求每个等级的点的数量. 显然的三维偏序问题,CDQ的板子题. CDQ分治: CDQ分治是一种 ...
随机推荐
- vagrant的centos镜像,怎么用root用户登录?
vagrant的centos镜像,默认用户和密码都是vagrant,如果要用root用户登录,应该怎么办呢? 百度了一下,有一篇博客是这样说的: 默认的登录用户是vagrant,如果想实现默认root ...
- Unable to handle kernel paging request at virtual address
1.Unable to handle kernel paging request at virtual address 00000000 =====>越出内核地址空间范围,原因是由于使用空NUL ...
- Java多线程之通过标识关闭线程
package org.study2.javabase.ThreadsDemo.status; /** * @Auther:GongXingRui * @Date:2018/9/19 * @Descr ...
- js函数使用prototype和不适用prototype的区别
js中类定义函数时用prototype与不用的区别 原创 2017年06月05日 12:25:41 标签: 函数 / prototype / class 首先来看一个实例: function Li ...
- eclipse 等号左边代码补全
1: 2. 3.完成 “ctrl + shift + l” 代码补全成功
- BZOJ3638[Codeforces280D]k-Maximum Subsequence Sum&BZOJ3272Zgg吃东西&BZOJ3267KC采花——模拟费用流+线段树
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- HDU 4256 翻译罗马数字
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6414173.html The Famous Clock Time Limit: 2000/1000 ...
- appium 原理解析(转载雷子老师博客)
appium 原理解析 原博客地址:https://www.cnblogs.com/leiziv5/p/6427609.html Appium是 c/s模式的appium是基于 webdriver 协 ...
- 配置Robot Framework 环境时如何查看wxPython是否成功安装
配置Robot Framework,win10系统,安装版本分别如下:
- SQL循环语句 详解
SQL循环语句 declare @i int set @i=1 while @i<30 begin insert into test (userid) values(@i) set @i=@i+ ...