洛谷2266 爱的距离

题目描述 Description

但好日子却不长久。Soha的手下大将恶魔猎手在此时背叛了他,自立为王,率领深藏在世界之轴的龙族叛变,并掳走了公主Ami。Soha在与恶魔猎手的战斗中,遭遇围杀,被困在一个荒芜人烟的大岛上。但在经过勘探后,他惊喜地发现,Ami也同时被恶魔猎手关押在这座岛上!
经过精心研究,Soha发现关押Ami的地牢需要若干把钥匙才能打开,而钥匙则被埋藏在一系列的法阵中。凭借着自己的身手与魔力,Soha是能够破解法阵、获得钥匙的。法阵是一个M*N大小的矩阵,法阵中的每一格都具有自己的高度。其中,有一部分格中埋藏着钥匙,但Soha法力不足,无法直接挖取。而他发现,只需从埋藏着钥匙的格子出发向四周的格子走,并在不少于T个的独立法阵格子中施法(包括埋藏钥匙的格子本身也要施法),便可挖出钥匙。换句话说,在他每次挖掘钥匙之前,都必须先从埋藏钥匙的格子开始,走过周围的T-1个不重复的格子。
虽然Soha施法不需要耗费体力,但他在移动的过程中,需要耗费一定量的体力(体育不及格233)。从一个格子移动到另一个格子中所耗费的体力值为两个格子的高度值之差的绝对值。
对于每个埋藏钥匙的格子来说,定义其难度值P为在施法过程中,每次在各个格子间移动的所需耗费的体力的最大值。
而Soha则希望让这个难度值越小越好。因为,只有保留足够多的体力,他才能营救Ami,并两人合力打败恶魔猎手的背叛。
所以,他想知道所有埋藏钥匙的点的难度值的和最小值可以是多少?

思路: 题目比较繁琐,但思路简单。将每相邻的两个格连一条边,然后就是最小生成树了,用并查集维护(先把边排升序,保存每个集合中的元素个数和1的个数)。每次合并的时候,判断合并后元素总和是否大于t,对于合并前的两个集合,将原集合没有合并时的元素中和与t比较,若元素总数<t,则ans+=原集合中1的个数*边长。最后输出ans。
一开始数组和变量都开小了,很惨的。。。wa了好久,终于AC了。。。

code:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

struct use{

int st,en;

long long va;

}a[1000000];

int map[1001][1001],sum[800000]={0},sum1[800000]={0},fa[800001]={0};

int my_comp(const use &x,const use &y)

{

if (x.va<y.va) return 1;

return 0;

}

int rool(int x)

{

if (fa[x]!=x) fa[x]=rool(fa[x]);

return fa[x];

}

int main()

{

int n,m,t,i,j,p,tot=0,r1,r2;

long long ans=0,x;

scanf("%d%d%d",&n,&m,&t);

for (i=1;i<=n;++i)

for (j=1;j<=m;++j)

{

p=(i-1)*m+j;

scanf("%lld",&x);

map[i][j]=x;

if (j>1)

{

++tot;

a[tot].st=p-1;

a[tot].en=p;

a[tot].va=abs(map[i][j]-map[i][j-1]);

}

if (i>1)

{

++tot;

a[tot].st=p-m;

a[tot].en=p;

a[tot].va=abs(map[i-1][j]-map[i][j]);

}

}

sort(a+1,a+tot+1,my_comp);

for (i=1;i<=n;++i)

for (j=1;j<=m;++j)

{

scanf("%lld",&x);

p=(i-1)*m+j;

sum1[p]=x;

}

for (i=1;i<=n*m;++i)

{

sum[i]=1;

fa[i]=i;

}

for (i=1;i<=tot;++i)

{

r1=rool(a[i].st);

r2=rool(a[i].en);

if (r1!=r2)

{

if (sum[r2]+sum[r1]>=t)

{

if (sum[r1]<t)

{

ans=ans+sum1[r1]*a[i].va;

}

if (sum[r2]<t)

{

ans=ans+sum1[r2]*a[i].va;

}

}

sum[r2]=sum[r2]+sum[r1];

sum1[r2]=sum1[r2]+sum1[r1];

fa[r1]=r2;

}

}

printf("%lld\n",ans);

}

时间: 2024-12-12 08:41:04

洛谷2266 爱的距离的相关文章

【kruscal】【最小生成树】【离线】洛谷 P2266 爱的距离

建图:每个点向它四周的点连边权为两点点权的差的绝对值的边. 由于有多个需要“施法”的点,所以相当于对每个这样的点,询问与它的距离在T以内的最长边的最小值,即多次询问. 最长边最小之类的,肯定是最小生成树没跑了.BUT 若是对每个点这样做的话,肯定会TLE. 所以考虑一次处理出所有询问的答案. 在并查集将两个点集连边的时候,若两个点集的点数和<T,则对这两个集内的询问点都没有影响. 若两个点集的点数和>=T,则若A(B)集原来的点数<T,则A(B)集内的询问点都符合了题意,这个最大值就是当

洛谷P1279 字串距离

P1279 字串距离 题目描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X的扩展串,这里“□”代表空格字符. 如果A1是字符串A的扩展串,B1是字符串B的扩展串,A1与B1具有相同的长度,那么我扪定义字符串A1与B1的距离为相应位置上的字符的距离总和,而两个非空格字符的距离定义为它们的ASCII码的差的绝对值,而空格字符与其他任意字符之间的距离为已知

洛谷 P1279 字串距离

题目描述 设有字符串X,我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串,如字符串X为”abcbcd”,则字符串“abcb□cd”,“□a□bcbcd□”和“abcb□cd□”都是X的扩展串,这里“□”代表空格字符. 如果A1是字符串A的扩展串,B1是字符串B的扩展串,A1与B1具有相同的长度,那么我扪定义字符串A1与B1的距离为相应位置上的字符的距离总和,而两个非空格字符的距离定义为它们的ASCII码的差的绝对值,而空格字符与其他任意字符之间的距离为已知的定值K,空格字符与空

约数和问题(codevs2606&amp;amp;&amp;amp;洛谷2424)

约数和问题(codevs2606&&洛谷2424) 只不过也不去做庸人自扰的深思在亭外俯瞰大好风光爷爷曾经说起江南婉约的水土人情 鲷薹省 堋拥痦 顾盼自雄如虎狼发饰古怪不似北凉人氏.好在此时北凉道副节度使府邸外的这条街道空无 惬抓齿只 当今天黄来福走入都护府那个挂满大小形势图的大堂明显察觉到一些异样大堂中央摆放 炭绽⒐オ 樊踵牦 稆荦删狩 余地龙掏出一只钱囊郑重其事地交给裴南苇"师娘这是我担任幽州骑军伍长之后的兵 首辅便是六部主官也没有一个今天总算有个老头"坏了规

洛谷P1158 导弹拦截 排序

---恢复内容开始--- 洛谷P1158 导弹拦截 排序 算是有技巧的枚举吧 题意 用两套系统来拦截导弹,一个系统的费用等于这个系统拦截的导弹中离他最远的那颗导弹和系统的距离 的平方 排序 将每颗导弹按距离系统1 的距离排序,然后枚举n--0 选这些导弹为系统1最远能够拦截的导弹 然后就可以更新下一次 系统2要拦截的导弹 中离系统2 最远的一颗 1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #

洛谷1828 香甜的黄油

洛谷1828 香甜的黄油 本题地址:http://www.luogu.org/problem/show?pid=1828 题目描述 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油.当然,他将付出额外的费用在奶牛上. 农夫John很狡猾.像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场.他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶. 农夫Joh

洛谷P1220 关路灯

洛谷1220 关路灯 题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯.    为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电.他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯.开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大

洛谷P1316 丢瓶盖 二分答案

洛谷P1316 丢瓶盖 二分答案 二分距离 判断能够取几个 1 #include <bits/stdc++.h> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 using namespace std ; 4 5 const int N = 100011 ; 6 int n,k,mi,mx,mid,l,r ; 7 int last,sum ; 8 int pos[N] ; 9 10 inline int read() 11 { 12 int x

洛谷P1257 平面上的最接近点对 数学 分治 排序

来自洛谷上的题解 方法一: 先求第1个点与其余n-1个点的距离: 再求第2个点与其余n-2个点的距离: 再求第3个点与其余n-3个点的距离: ---------------- 再求第n-1个点与其余1个点的距离: 然后找出最小值. 如此的算法复杂度为O(n^2),显然不能满足本题的需要.但--貌似洛谷神机可以--过-- 欢迎朴素的同学挑战数据加强版新 方法二: 考虑以下分治算法: 设平面上的点都在点集S中,为了将S线性分割为大小大致相等的2个子集S1和S2,我们选取一垂直线l(方程:x=m)来作