[NOI2019]弹跳(KD-Tree/四分树/线段树套平衡树 优化建图+Dijkstra)
本题可以用的方法很多,除去以下三种我所知道的就还有至少三种。
方法一:类似线段树优化建图,将一个平面等分成四份(若只有一行或一列则等分成两份),然后跑Dijkstra即可。建树是$O(n\log n)$的,单次连边是$O(n\log^2 n)$的。
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=,M=;
struct E{ int w,l,r,u,d; }p[N];
struct P{ int u,d; };
vector<int>G[N];
int n,m,W,H,now,dis,x,y,cnt,rt,tot,h[N],to[M],nxt[M],w[M],vis[N],d[N],ch[N][];
bool operator <(P x,P y){ return x.d>y.d; }
priority_queue<P>Q;
void add(int x,int y,int z){ to[++cnt]=y; nxt[cnt]=h[x]; w[cnt]=z; h[x]=cnt; } void ins(int fa,int &k,int xl,int xr,int yl,int yr,int x,int y){
if (x<xl||x>xr||y<yl||y>yr) return;
if (!k) k=++tot;
if (k!=rt) add(fa+n,k+n,);
if (xl==xr&&yl==yr){ add(k+n,now,); return; }
int xm=(xl+xr)>>,ym=(yl+yr)>>;
ins(k,ch[k][],xl,xm,yl,ym,x,y);
ins(k,ch[k][],xl,xm,ym+,yr,x,y);
ins(k,ch[k][],xm+,xr,yl,ym,x,y);
ins(k,ch[k][],xm+,xr,ym+,yr,x,y);
} void link(int k,int xl,int xr,int yl,int yr,int xL,int xR,int yL,int yR){
if (!k||xR<xl||xL>xr||yR<yl||yL>yr||d[k+n]<=dis) return;
if (xl>=xL&&xr<=xR&&yl>=yL&&yr<=yR){ d[k+n]=dis; Q.push((P){k+n,d[k+n]}); return; }
int xm=(xl+xr)>>,ym=(yl+yr)>>;
link(ch[k][],xl,xm,yl,ym,xL,xR,yL,yR);
link(ch[k][],xl,xm,ym+,yr,xL,xR,yL,yR);
link(ch[k][],xm+,xr,yl,ym,xL,xR,yL,yR);
link(ch[k][],xm+,xr,ym+,yr,xL,xR,yL,yR);
} int main(){
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&W,&H);
rep(i,,n) scanf("%d%d",&x,&y),now=i,ins(,rt,,W,,H,x,y);
rep(i,,m) scanf("%d%d%d%d%d%d",&now,&p[i].w,&p[i].l,&p[i].r,&p[i].u,&p[i].d),G[now].push_back(i);
memset(d,,sizeof(d)); d[]=; Q.push((P){,});
while (!Q.empty()){
int u=Q.top().u; Q.pop();
if (vis[u]) continue; vis[u]=;
for (int i=;i<(int)G[u].size();i++)
x=G[u][i],dis=d[u]+p[x].w,link(rt,,W,,H,p[x].l,p[x].r,p[x].u,p[x].d);
For(i,u) if (d[k=to[i]]>d[u]+w[i]) Q.push((P){k,d[k]=d[u]+w[i]});
}
rep(i,,n) printf("%d\n",d[i]);
return ;
}
四分树
方法二:一维使用线段树,另一维用set维护这行中的每个点。注意到在Dijikstra时,一条边至多被松弛一次,即一个矩阵至多被访问一次,所以访问并更新一个点之后就可以直接将其删去,复杂度$O(n\log^2 n+m\log m)$。
#include<set>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,l,mid
#define rson rs,mid+1,r
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std;
typedef pair<int, int>pii;
typedef multiset<pii>::iterator iter; const int N=,M=,S=(<<)+;
int n,m,W,H,x,p,id,yp[N],vis[N],dis[N],h[N],nxt[M],val[M],L[M],R[M],D[M],U[M];
multiset<pii>st[S];
priority_queue<pii> Q; void ins(int x,int l,int r,int k,int id){
st[x].insert(pii(yp[id],id));
if (l==r) return;
int mid=(l+r)>>;
if (k<=mid) ins(lson,k,id); else ins(rson,k,id);
} void del(int x,int l,int r,int id,int d){
if (r<L[id] || R[id]<l) return;
if (L[id]<=l && r<=R[id]){
iter it=st[x].lower_bound(pii(D[id],)),tmp;
while (it!=st[x].end() && it->first<=U[id]){
int u=it->second;
if (!vis[u]){
vis[u]=; dis[u]=d;
for (int j=h[u]; j; j=nxt[j]) Q.push(pii(-d-val[j],j));
}
tmp=it; it++; st[x].erase(tmp);
}
return;
}
int mid=(l+r)>>; del(lson,id,d); del(rson,id,d);
} int main(){
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&W,&H);
rep(i,,n) scanf("%d%d",&x,&yp[i]),ins(,,W,x,i);
rep(i,,m) scanf("%d%d%d%d%d%d",&p,&val[i],&L[i],&R[i],&D[i],&U[i]),nxt[i]=h[p],h[p]=i;
dis[]=; vis[]=;
for (int i=h[]; i; i=nxt[i]) Q.push(pii(-val[i],i));
while (!Q.empty()){
pii ed=Q.top(); Q.pop();
int dis=-ed.first; id=ed.second; del(,,W,id,dis);
}
rep(i,,n) printf("%d\n",dis[i]);
return ;
}
线段树套set
方法三:类似方法二地,用KD-Tree优化建图,树上每个点新建一个新点,每个叶子连向这个坐标对应的点。同样在Dijkstra时,每次访问并更新时删除这个点。复杂度可能可以用一些做到$O(n\log^2 n)$,但这里没用。
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
using namespace std; const int N=,inf=0x3f3f3f3f;
int n,m,w,h,rt,D,cnt,id[N*],dis[N*],vis[N*];
int nu,nt,xl,xr,yl,yr,nd[N*],len; struct data{
int nt,xl,xr,yl,yr;
bool operator>(const data &b)const{ return nt>b.nt; }
}; vector<data>f[N*];
priority_queue<data,vector<data>,greater<data> >Q; struct P{
int x[],id;
bool operator<(const P&b)const{ return x[D]!=b.x[D] ? x[D]<b.x[D] : x[D^]<b.x[D^]; }
}p[N]; struct Tr{ int mx[],mn[],lc,rc,siz; }t[N*]; void upd(int u){
t[u].mn[]=t[u].mn[]=inf;
t[u].mx[]=t[u].mx[]=-inf;
t[u].siz=; int v=t[u].lc;
if (v){
t[u].siz+=t[v].siz;
t[u].mx[]=max(t[u].mx[],t[v].mx[]),t[u].mx[]=max(t[u].mx[],t[v].mx[]);
t[u].mn[]=min(t[u].mn[],t[v].mn[]),t[u].mn[]=min(t[u].mn[],t[v].mn[]);
}
v=t[u].rc;
if (v){
t[u].siz+=t[v].siz;
t[u].mx[]=max(t[u].mx[],t[v].mx[]),t[u].mx[]=max(t[u].mx[],t[v].mx[]);
t[u].mn[]=min(t[u].mn[],t[v].mn[]),t[u].mn[]=min(t[u].mn[],t[v].mn[]);
}
} int bud(int l,int r,int wd){
int u=++cnt,mid=(l+r)>>;t[u].siz=;
if (l==r){
id[u]=p[l].id;
t[u].mn[]=t[u].mx[]=p[l].x[];
t[u].mn[]=t[u].mx[]=p[l].x[];
return u;
}
bool flag=;
rep(i,l+,r) if(p[i].x[wd]!=p[i-].x[wd])flag=;
if (flag) wd^=;
D=wd; nth_element(p+l,p+mid,p++r);
t[u].lc=bud(l,mid,wd^); t[u].rc=bud(mid+,r,wd^);
upd(u); return u;
} void dfs(int u){
if (!t[u].siz)return;
if (t[u].mn[]>xr||t[u].mx[]<xl||t[u].mn[]>yr||t[u].mx[]<yl)return;
if (id[u]){ nd[++len]=id[u]; t[u].siz=; return; }
dfs(t[u].lc); dfs(t[u].rc);
t[u].siz=t[t[u].lc].siz+t[t[u].rc].siz;
} int main(){
freopen("jump.in","r",stdin);
freopen("jump.out","w",stdout);
memset(dis,,sizeof(dis));
scanf("%d%d%d%d",&n,&m,&w,&h);
rep(i,,n) scanf("%d%d",&p[i].x[],&p[i].x[]),p[i].id=i;
rt=bud(,n,);
rep(i,,m){
scanf("%d%d%d%d%d%d",&nu,&nt,&xl,&xr,&yl,&yr);
f[nu].push_back((data){nt,xl,xr,yl,yr});
}
dis[]=; vis[]=;
for(int i=; i<(int)f[].size(); i++) Q.push(f[][i]);
while (!Q.empty()){
nt=Q.top().nt,xl=Q.top().xl,xr=Q.top().xr,yl=Q.top().yl,yr=Q.top().yr;
Q.pop(); len=; dfs(rt);
rep(i,,len){
int u=nd[i];
if (vis[u])continue; vis[u]=;
dis[u]=nt;
for (int j=; j<(int)f[u].size(); ++j){
data tp=f[u][j]; tp.nt+=nt; Q.push(tp);
}
}
}
rep(i,,n) printf("%d\n",dis[i]);
return ;
}
KD-Tree
[NOI2019]弹跳(KD-Tree/四分树/线段树套平衡树 优化建图+Dijkstra)的更多相关文章
- CF1007D. Ants(树链剖分+线段树+2-SAT及前缀优化建图)
题目链接 https://codeforces.com/problemset/problem/1007/D 题解 其实这道题本身还是挺简单的,这里只是记录一下 2-SAT 的前缀优化建图的相关内容. ...
- Wannafly Winter Camp 2020 Day 5I Practice for KD Tree - 二维线段树
给定一个 \(n \times n\) 矩阵,先进行 \(m_1 \leq 5e4\) 次区间加,再进行 \(m_2 \leq 5e5\) 次询问,每次询问要求输出矩形区间内的最大数.\(n \leq ...
- BZOJ3073: [Pa2011]Journeys(线段树优化建图 Dijkstra)
题意 \(n\)个点的无向图,构造\(m\)次边,求\(p\)到任意点的最短路. 每次给出\(a, b, c, d\) 对于任意\((x_{a \leqslant x \leqslant b}, y_ ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- 2016湖南省赛 I Tree Intersection(线段树合并,树链剖分)
2016湖南省赛 I Tree Intersection(线段树合并,树链剖分) 传送门:https://ac.nowcoder.com/acm/contest/1112/I 题意: 给你一个n个结点 ...
- [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...
- 洛谷3783 SDOI2017 天才黑客(最短路+虚树+边转点+线段树优化建图)
成功又一次自闭了 怕不是猪国杀之后最自闭的一次 一看到最短路径. 我们就能推测这应该是个最短路题 现在考虑怎么建图 根据题目的意思,我们可以发现,在本题中,边与边之间存在一些转换关系,但是点与点之间并 ...
- Codeforces 1045A Last chance 网络流,线段树,线段树优化建图
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045A.html 题目传送们 - CF1045A 题意 你有 $n$ 个炮,有 $m$ 个敌人,敌人排成一 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
随机推荐
- ffmpeg结合SDL编写播放器(一)
ffmpeg 工具是一个高效快速的命令行工具,进行视音频不同格式之间的转换. ffmpeg命令行 ffmpeg可以读取任意数量的输入“文件”(可以是常规文件,管道,网络流,抓取设备等)读取,由 -i ...
- shell 求数组的平均值,求和,最大值,最小值
test.sh #!/bin/bash arr=( ) let min=${arr[]} let max=${min} sum= ;i<${#arr[*]};i++)) do [[ ${min} ...
- Fluent使用UDF遇见Received signal SIGSEGV
Fluent版本:19.0 究其原因,一般是因为我们编写的UDF当中指针错误,导致未能正确获取Fluent一些变量的值,从而造成该错误. 下面我们通过调试手段来为了重现该错误,直观查看错误原因. 我们 ...
- OpenFOAM——设置非均匀边界方法总结
在使用OpenFOAM求解的时候我们经常需要设置非均匀的边界,比如我们在计算层流的时候,很多时候需要入口为充分发展的入口边界,下面我们就以入口处为充分发展的层流速度分布为总结OpenFOAM当中设定不 ...
- 《京东B2B业务架构演变》阅读笔记
一.京东 B2B 业务的定位 让各类型的企业都可以在京东的 B 平台上进行采购.建立采购关系. 京东 B2B 的用户群体主要分为 2 类: 一类是大 B 用户.另一类是小 B 用户.京东 B 平台需要 ...
- vue.js动态绑定input的checked
不管<input type='radio checked='true''> 你的checked属性值是true或者false,他都会选中. 其实原理是这样的,复选框里只要有checked ...
- 解决IDEA中maven导入jar包
查 看: File------>Project Structure--------->Libraries如下面没有maven所引入的jar包则为该错误[1] 错误原因: 是 ...
- Redis的内存回收策略和内存上限(阿里)
还有一篇文章 讲解guava如何删除过期数据的,与redis不同,guava没有维护线程删除过期key,只是在设置 key 或者 读取key的时候,顺带删除参考:GuavaCache简介(一)是轻量级 ...
- template cannot be keyed. Place the key on real elements instead.
template cannot be keyed. Place the key on real elements instead. 一.总结 一句话总结: 原因:vue不支持在 template 元素 ...
- 【HBase】HBase 单机版安装及使用
HBase介绍 HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”.就像Bigtable利用了 ...