曼哈顿距离最小生成树 codechef Dragonstone
曼哈顿距离最小生成树
codechef Dragonstone
首先,对于每一个点来说有用的边只有它向它通过 x=0,y=0,y=x,y=-x 切出来的八个平面的最近点。
证明 我不会
反正当结论记住就行了
然后我们就只需要考虑右上这个区间的点(因为看起来最好做)
其他的区间可以通过坐标变换到这个区间,并且因为边是双向的,可以只考虑y=-x切出来的右上的这四个区间。
对于一个点 $ B(x_1,y_1) $ 和这里的点 $ A(x_0,y_0) $ B是合法的当且仅当 $ x_1 > x_0 , y_1 > y_0 , x_1-x_0 \leq y_1 - y_0 $
再推一下,发现 $ y_1 > y_0 $ 这个条件然并卵,因为第三个条件和第一个条件已经限制了它
所以我们可以看成这两个式子 $ x_1 > x_0 , x_1 - y_1 \leq x_0 - y_0 $
同时,需要满足 $ x_1 + y_1 $ 尽量小
把 $ x_1 + y_1 $ 当成权值加入线段树,位置在 $ x_1 - y_1 $ 就好了
差需要离散化
别忘多组。。wa了好多次。。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
#define int long long
#define MAXN 800006
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define inf 0x3f3f3f3f3f3f3f3f
int n , q;
namespace SGT {
pii T[MAXN << 2];
void pushup( int rt ) {
T[rt] = min( T[rt << 1] , T[rt << 1 | 1] );
}
void build( int rt , int l , int r ) {
T[rt] = mp( inf , inf );
if( l == r ) return;
int m = l + r >> 1;
build( rt << 1 , l , m ) , build( rt << 1 | 1 , m + 1 , r );
}
void mdfy( int rt , int l , int r , int p , pii c ) {
if( l == r && p == l ) { T[rt] = min( T[rt] , c ); return; }
int m = l + r >> 1;
if( p <= m ) mdfy( rt << 1 , l , m , p , c );
else mdfy( rt << 1 | 1 , m + 1 , r , p , c );
pushup( rt );
}
pii que( int rt , int l , int r , int L , int R ) {
if( L <= l && R >= r ) return T[rt];
int m = l + r >> 1; pii res = mp( inf , inf );
if( L <= m ) res = min( res , que( rt << 1 , l , m , L , R ) );
if( R > m ) res = min( res , que( rt << 1 | 1 , m + 1 , r , L , R ) );
return res;
}
}
#define mx 600000
struct point{
int x , y , id;
} P[MAXN] ;
bool cmp( point x , point y ) {
return x.x == y.x ? x.y > y.y : x.x > y.x;
}
int A[MAXN] , a[MAXN];
struct edge{
int u , v , w;
} E[MAXN] ; int ecn;
void doit( ) {
sort( P + 1 , P + 1 + n , cmp );
for( int i = 1 ; i <= n ; ++ i ) A[i] = P[i].x - P[i].y;
sort( A + 1 , A + 1 + n );
int sz = unique( A + 1 , A + 1 + n ) - A - 1;
for( int i = 1 ; i <= n ; ++ i ) a[i] = lower_bound( A + 1 , A + 1 + sz , P[i].x - P[i].y ) - A ;
SGT::build( 1 , 1 , mx );
pii res = mp( 0 , 0 );
for( int i = 1 ; i <= n ; ++ i ) {
pii fd = SGT::que( 1 , 1 , mx , 1 , a[i] );
if( fd.se != 0x3f3f3f3f3f3f3f3f )
E[++ecn] = ( edge ) { P[i].id , fd.se , - P[i].x - P[i].y + fd.fi };
SGT::mdfy( 1 , 1 , mx , a[i] , mp( P[i].x + P[i].y , P[i].id ) );
}
}
bool cmpp( edge a , edge b ) {
return a.w < b.w;
}
int fa[MAXN];
int find( int x ) {
return x == fa[x] ? x : fa[x] = find( fa[x] );
}
namespace tree {
int head[MAXN] , nex[MAXN] , to[MAXN] , wto[MAXN] , cn;
void ade( int u , int v , int w ) {
nex[++cn] = head[u] , to[cn] = v , wto[cn] = w , head[u] = cn;
}
#define MAXK 20
int G[MAXN][MAXK][2];
int dep[MAXN];
void init( ) {
dep[1] = 0;
memset( head , 0 , sizeof head );
memset( G , 0 , sizeof G );
cn = 0;
}
void dfs( int u , int fa ) {
dep[u] = dep[fa] + 1;
for( int i = head[u] ; i ; i = nex[i] ) {
int v = to[i];
if( v == fa ) continue;
G[v][0][0] = u , G[v][0][1] = wto[i];
for(int j = 1 ; j < 20 ; ++ j)
if(G[G[v][j - 1][0]][j - 1][0])
G[v][j][0] = G[G[v][j-1][0]][j-1][0],G[v][j][1] = max(G[v][j-1][1],G[G[v][j-1][0]][j-1][1]);
else break;
dfs( v , u );
}
}
int que( int u , int v ) {
if( dep[u] < dep[v] ) swap( u , v );
int suml = -inf , sumr = -inf;
if( dep[u] != dep[v] )
for( int k = MAXK - 1 ; k >= 0 ; -- k )
if( dep[G[u][k][0]] >= dep[v] )
suml = max( suml , G[u][k][1] ) , u = G[u][k][0];
if( u == v ) return max( suml , sumr );
for( int k = MAXK - 1 ; k >= 0 ; -- k )
if( G[u][k][0] != G[v][k][0] )
suml = max( suml , G[u][k][1] ) , sumr = max( sumr , G[v][k][1] ),
u = G[u][k][0] , v = G[v][k][0];
suml = max( suml , G[u][0][1] ) , sumr = max( sumr , G[v][0][1] );
return max( suml , sumr );
}
}
signed main( ) {
freopen("fuck.in","r",stdin);
int T;cin >> T;
while( T-- ) {
cin >> n;
ecn = 0;
for( int i = 1 , u , v ; i <= n ; ++ i )
scanf("%lld%lld",&P[i].x,&P[i].y) , P[i].id = i;
doit( );
for( int i = 1 ; i <= n ; ++ i ) swap( P[i].x , P[i].y );
doit( );
for( int i = 1 ; i <= n ; ++ i ) P[i].x = -P[i].x;
doit( );
for( int i = 1 ; i <= n ; ++ i ) swap( P[i].x , P[i].y );
doit( );
sort( E + 1 , E + 1 + ecn , cmpp );
tree::init( );
for( int i = 1 ; i <= n ; ++ i ) fa[i] = i;
for( int i = 1 ; i <= ecn ; ++ i ) if( find( E[i].u ) != find( E[i].v ) )
fa[find( E[i].u )] = find( E[i].v ) ,
tree::ade( E[i].u , E[i].v , E[i].w ) ,
tree::ade( E[i].v , E[i].u , E[i].w );
tree::dfs( 1 , 1 );
cin >> q;
int u , v;
while( q-- ) {
scanf("%lld%lld",&u,&v);
printf("%lld\n",tree::que( u , v ));
}
}
}
曼哈顿距离最小生成树 codechef Dragonstone的更多相关文章
- 【POJ 3241】Object Clustering 曼哈顿距离最小生成树
http://poj.org/problem?id=3241 曼哈顿距离最小生成树模板题. 核心思想是把坐标系转3次,以及以横坐标为第一关键字,纵坐标为第二关键字排序后,从后往前扫.扫完一个点就把它插 ...
- 51nod 1213 二维曼哈顿距离最小生成树
1213 二维曼哈顿距离最小生成树 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间 ...
- [51nod1213]二维曼哈顿距离最小生成树
二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离).求这N个点所组成的完全图 ...
- LA 3662 Another Minimum Spanning Tree (曼哈顿距离最小生成树 模板)
题目大意: 曼哈顿最小距离生成树 算法讨论: 同上. 这回的模板真的准了. #include <iostream> #include <cstring> #include &l ...
- POJ 3241 曼哈顿距离最小生成树 Object Clustering
先上几个资料: 百度文库有详细的分析和证明 cxlove的博客 TopCoder Algorithm Tutorials #include <cstdio> #include <cs ...
- POJ 3241Object Clustering曼哈顿距离最小生成树
Object Clustering Description We have N (N ≤ 10000) objects, and wish to classify them into several ...
- 曼哈顿距离MST
https://www.cnblogs.com/xzxl/p/7237246.html 讲的不错 /* 曼哈顿距离最小生成树 poj 3241 Object Clustering 按照上面的假设我们先 ...
- Hdu4311 || 4312Meeting point-1/-2 n个点中任意选一个点使得其余点到该点曼哈顿距离之和最小
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离
Atitti knn实现的具体四个距离算法 欧氏距离.余弦距离.汉明距离.曼哈顿距离 1. Knn算法实质就是相似度的关系1 1.1. 文本相似度计算在信息检索.数据挖掘.机器翻译.文档复制检测等领 ...
随机推荐
- STM32中操作寄存器GPIOB_CRL &= ~( 0x0F<< (4*0))与GPIOB_CRL &=~(0x0F)之间有什么区别吗?
没有区别,作用相同.只是这样写便于修改和沿用. 对于只用到PB0端口的程序~(0x0f << (4*0)) 和~0x0f没有区别.0x0f <<(4*N) 就是 向左 移动N个 ...
- 【UE4 C++】Tick的三种方式、异步蓝图节点
Tick的三种方式 包括 默认 Tick (Actor.Component.UMG) TimerManager 定时器 FTickableGameObject 可以写原生 Object 也可以继承UO ...
- 【UE4 设计模式】命令模式 Command Pattern
概述 描述 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务 ...
- BUAA2020软工作业(四)——结对项目
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目作业 我在这个课程的目标是 进一步提高自己的编码能力,工程能力,团队协作能力 这个作业在哪 ...
- Noip模拟43 2021.8.18
T1 地一体 可以树形$dp$,但考场没写出来,只打了没正确性的贪心水了$30$ 然后讲题的时候B哥讲了如何正确的贪心,喜出望外的学习了一下 不难发现 每次士兵都会直接冲到叶子节点 从深的点再返回到另 ...
- stm32串口USART 硬件流控 --学习笔记
流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口.流控的定义.大家一定了解,RS232 中的"RS"是Recommend Standard 的缩写,即&qu ...
- F. Mattress Run 题解
F. Mattress Run 挺好的一道题,对于DP的本质的理解有很大的帮助. 首先要想到的就是将这个拆成两个题,一个dp光求获得足够的夜晚的最小代价,一个dp光求获得足够的停留的最小代价. 显然由 ...
- MySQL怎么缓解读的压力的?---buffer pool
每当我们想要缓解读,一般会想到什么? 预读取,缓存 缓存 缓存,其实就是将高频访问的数据放到内存里面,减少读盘的次数. 为了提高内存的利用率,MySQL还建立了缓存池,也就是buffer pool,存 ...
- ES6-变量的解构赋值复习+学习
ES6------变量的解构赋值 由于之前学过ES6的解构赋值,但是只是略看了一点网上的视频,所以今天就看了看ES6对这一部分的详细介绍,然后做一个总结的笔记. 首先,先大概说一下什么是变量的解构赋值 ...
- makefile编译子目录
make子目录常用方法 一般是 SUB_DIR = lib_src service .PHONY: subdirs $(SUB_DIR) subdirs: $(SUB_DIR) $(SUB_DIR): ...