2019.8.16

T2 water

官方题解:

一个块的水平面高度就是从这个块走出矩形的所有路径上的最 大值的最小值。

相邻块连边,权值为两块的较大值,矩形 边界的块向“矩形外”连边,权值为 max(高度,0)。

做最小生成树。

时间复杂度 O(nmlognm)。

瓶颈生成树:满足最大的边最小。

最小生成树:也就是最小瓶颈树。

我来说说:

1.为什么能用最小生成树??

  正如题解,一个格子的水是由它流向外围的所有路径中,每条路径上的最大值     的最小值。(木桶原理)

  可以用bfs解决。

  最小生成树可以求出最小的路径,再在该路径上取最大值即为最大蓄水量。

2.一开始想的是对每一个格子kruscal,但发现可以一次解决所有答案。

3.对每一个点,寻找该点所在联通块时,O(N)遍历会TLE(70),用vector解决。

好题,难想。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=310;
 4 const int N=maxn*maxn*4;
 5 const int mod=1e9+7;
 6 int dx[]={0,1,-1,0,0};
 7 int dy[]={0,0,0,1,-1};
 8 int n,m;
 9 int zb(int i,int j){return (i-1)*m+j;}
10 int mp[maxn][maxn],cnt[maxn][maxn];
11 struct Edge{
12     int w,f,to,nxt;
13     bool operator < (const Edge &b) const {
14         return w<b.w;
15     }
16 }ed[N];
17 int head[N],ecnt;
18 void addedge(int f,int to,int w){
19     ed[++ecnt].w=w;
20     ed[ecnt].f=f;
21     ed[ecnt].to=to;
22     ed[ecnt].nxt=head[f];
23     head[f]=ecnt;
24 }
25 int fa[N],ans[N];
26 int find(int x){
27     if(fa[x]==x) return x;
28     return fa[x]=find(fa[x]);
29 }
30 vector <int> v[N];
31 void deal_(){
32     for(int i=0;i<=n*m;i++) fa[i]=i,v[i].push_back(i);
33     int target=0;
34     for(int i=1;i<=ecnt;i++){
35         int a=ed[i].f,b=ed[i].to;
36         int ffa=find(a),ffb=find(b);
37         if(ffa!=ffb){
38             if(ffb==target&&ffa!=target) swap(ffa,ffb),swap(a,b);
39             if(ffa==target){
40                 for(int j=0;j<v[ffb].size();j++){
41                     ans[v[ffb][j]]=ed[i].w;
42                 }
43             }
44             fa[ffb]=ffa;
45             for(int j=0;j<v[ffb].size();j++){
46                 v[ffa].push_back(v[ffb][j]);
47             }
48         }
49     }
50 }
51 int main(){
52     scanf("%d%d",&n,&m);
53     for(int i=1;i<=n;i++)
54         for(int j=1;j<=m;j++)
55             scanf("%d",&mp[i][j]);
56     for(int i=1;i<=n;i++)
57         for(int j=1;j<=m;j++){
58             for(int d=1;d<=4;d++){
59                 if(i+dx[d]<=0||i+dx[d]>n||j+dy[d]<=0||j+dy[d]>m){
60                     addedge(0,zb(i,j),max(mp[i][j],0));
61 //                    addedge(zb(i,j),0,max(mp[i][j],0));
62                     continue;
63                 }
64                 addedge(zb(i,j),zb(i+dx[d],j+dy[d]),max(mp[i][j],mp[i+dx[d]][j+dy[d]]));
65 //                addedge(zb(i+dx[d],j+dy[d]),zb(i,j),max(mp[i][j],mp[i+dx[d]][j+dy[d]]));
66             }
67         }
68     sort(ed+1,ed+1+ecnt);
69     memset(ans,-1,sizeof ans);
70     deal_();
71     for(int i=1;i<=n;i++){
72         for(int j=1;j<=m;j++){
73             printf("%d ",ans[zb(i,j)]-mp[i][j]);
74         }
75         puts("");
76     }
77     return 0;
78
79 }

原文地址:https://www.cnblogs.com/sdfzjdx/p/11366829.html

时间: 2024-08-30 14:21:16

2019.8.16的相关文章

[Intern][2019.03.16]针对已有的HTML如何只凭JS改动?

刚入职的时候看到公司用的HTML日志生成工具附带的Panel,工具不够用,找个Fail还要找半天,于是自己琢磨着添砖加瓦.以前也是个半吊子前端工程师,现在可倒好,想要改页面却连页面生成的模板在哪里都不知道,只有通过改动JavaScript才能实现对页面的修改. 固然,操作DOM有原版的 document.getElementsBy 一族,可是它们get的时候不能通过 class 和 标签 来区分,比如: <div class="FAIL"> <tr class=&qu

2019.3.16 最小生成树之城市改造

题目描述 作为规划局长的你接到了城市C的改造任务:城市中有n个标志性建筑,要在这n个标志性建筑之间修建双向道路,使得这n个标志性建筑之间相互连通,以最大程度地方便游客来访.由于市政府资金有限,所以希望成本尽可能低.建设费用有两种支付方式:1. 施工公司给出m种套餐供选择,每种套餐可以将方案中的所有标志性建筑连通,总花费为Ci:2. 单独铺设两个标志物之间道路,费用为两个标志物之间的欧式距离的平方.现在要求你选择最佳的建设方案(可以选择任意个套餐以及铺设任意条道路). 输入 输入第一行包括两个整数

2019.5.16 课后练习。简易购物车程序

根据之前看过的知识点,以自己的思路先写出了一个程序,后续继续老师的操作再进行优化. 1 salary = int(input("请输入您的工资(单位 元):")) 2 3 print("以下是可购清单:") 4 5 shopping_list = ['','iphone','computer','book','apple_juice','bread','cake']#商品列表 6 commodity_prices = [0,6000,7000,2,3,3,5] #商

2019.10.16&amp;17小结

话说也蛮久没写小结了,主要这两次考试失分严重,还是总结下吧. 10.16 T1 小奇挖矿2 100/0 [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿石交易市场,以便为飞船升级无限非概率引擎. [问题描述] 现在有m+1个星球,从左到右标号为0到m,小奇最初在0号星球. 有n处矿体,第i处矿体有ai单位原矿,在第bi个星球上. 由于飞船使用的是老式的跳跃引擎,每次它只能从第x号星球移动到第x+4号星球或x+7号星球.每到一个星球,小奇会采走该星球上所有的

@CSP模拟2019.10.16 - [email&#160;protected] 垃圾分类

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 为了保护环境,p6pou建设了一个垃圾分类器. 垃圾分类器是一个树形结构,由 n 个垃圾桶和 n-1 条双向传送带组成. 垃圾处理器的编号为 1, 2, ..., n,每条传送带都可以花 1 秒钟将垃圾从一个垃圾桶输送到另一个垃圾桶. 垃圾投放点是编号为 r 的垃圾桶,垃圾总是投放在这

解题报告-2019.12.16

解题报告-2019.12 题目:6-3[拓展编程题_课后练习3][P215 习题8-三-4] 报数 (20分) 题目详情: 报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号.从第一个人开始报数,报到m(<n)的人退出圈子:下一个人从1开始报数,报到m的人退出圈子.如此下去,直到留下最后一个人. 本题要求编写函数,给出每个人的退出顺序编号. 函数接口定义:void CountOff( int n, int m, int out[] ); 其中n是初始人数:m是游戏规定的退出位次(保证为小于

2019.2.16线段树模板

#include <stdio.h>#include <algorithm>#include <iostream>#include <string.h>#include <string>using namespace std;const int maxen=5000;int a[maxen+5],st[(maxen<<2)+5]; //a函数为主函数读入的数组,st为需要查询的数的信息,树的空间大小的四倍: void build(in

2019.3.16错过的计算题-应用统计学

1统计学 对于正态分布,这个关系很重要! (x-u)/ ---------------------- 参数估计类的题目: 无偏估计量: --------------- 置信区间 ---------------------- 假设类的题目:这个考的概率比较大 --------------------- 线性回归的计算题不会考到吧? 原文地址:https://www.cnblogs.com/huangbaobaoi/p/10539244.html

大数据学习2019.03.16

Java EE进阶——面向对象程序设计01 资料库的故事 package dome; public class CD { private String title; private String artist; private int numOfTracks; private int playingTime; private boolean gotIt = false; private String comment; public CD(String title, String artist,