2022-03-11每日刷题打卡

一、洛谷P1119 灾后重建

(1)问题描述

        

题目背景

B 地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。

题目描述

给出 B 地区的村庄数 NN,村庄编号从 00 到 N-1N−1,和所有 MM 条公路的长度,公路是双向的。并给出第 ii 个村庄重建完成的时间 t_iti​,你可以认为是同时开始重建并在第 t_iti​ 天重建完成,并且在当天即可通车。若 t_iti​ 为 00 则说明地震未对此地区造成损坏,一开始就可以通车。之后有 QQ 个询问 (x,y,t)(x,y,t),对于每个询问你要回答在第 tt 天,从村庄 xx 到村庄 yy 的最短路径长度为多少。如果无法找到从 xx 村庄到 yy 村庄的路径,经过若干个已重建完成的村庄,或者村庄 xx 或村庄 yy 在第 tt 天仍未重建完成,则需要返回 -1

输入格式

第一行包含两个正整数N,MN,M,表示了村庄的数目与公路的数量。

第二行包含NN个非负整数t_0, t_1,…, t_{N-1}t0​,t1​,…,tN−1​,表示了每个村庄重建完成的时间,数据保证了t_0 ≤ t_1 ≤ … ≤ t_{N-1}t0​≤t1​≤…≤tN−1​。

接下来MM行,每行33个非负整数i, j, wi,j,w,ww为不超过1000010000的正整数,表示了有一条连接村庄ii与村庄jj的道路,长度为ww,保证i≠ji=j,且对于任意一对村庄只会存在一条道路。

接下来一行也就是M+3M+3行包含一个正整数QQ,表示QQ个询问。

接下来QQ行,每行33个非负整数x, y, tx,y,t,询问在第tt天,从村庄xx到村庄yy的最短路径长度为多少,数据保证了tt是不下降的。

输出格式

共QQ行,对每一个询问(x, y, t)(x,y,t)输出对应的答案,即在第tt天,从村庄xx到村庄yy的最短路径长度为多少。如果在第t天无法找到从xx村庄到yy村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄yy在第tt天仍未修复完成,则输出-1−1。

输入输出样例

输入 #1复制

4 5
1 2 3 4
0 2 1
2 3 1
3 1 2
2 1 4
0 3 5
4
2 0 2
0 1 2
0 1 3
0 1 4

输出 #1复制

-1
-1
5
4

说明/提示

对于30\%30%的数据,有N≤50N≤50;

对于30\%30%的数据,有t_i= 0ti​=0,其中有20\%20%的数据有t_i = 0ti​=0且N>50N>50;

对于50\%50%的数据,有Q≤100Q≤100;

对于100\%100%的数据,有N≤200N≤200,M≤N \times (N-1)/2M≤N×(N−1)/2,Q≤50000Q≤50000,所有输入数据涉及整数均不超过100000100000。

(2)代码实现

        

#include<iostream>
#include<cstdio>
#define N 205
using namespace std;
int n,m;
int a[N];
int f[N][N];
inline void updata(int k){
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
	if(f[i][j]>f[i][k]+f[j][k])
	f[i][j]=f[j][i]=f[i][k]+f[j][k];
	return;
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
	scanf("%d",a+i);
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++){
		f[i][j]=1e9;
	}
	for(int i=0;i<n;i++)
	f[i][i]=0;
	int s1,s2,s3;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&s1,&s2,&s3);
		f[s1][s2]=f[s2][s1]=s3;
	}
	int q;
	cin>>q;
	int now=0;
	for(int i=1;i<=q;i++){
		scanf("%d%d%d",&s1,&s2,&s3);
		while(a[now]<=s3&&now<n){
			updata(now);
			now++;
		}
		if(a[s1]>s3||a[s2]>s3)cout<<-1<<endl;
		else {
			if(f[s1][s2]==1e9)cout<<-1<<endl;
			else cout<<f[s1][s2]<<endl;
		}
	}
	return 0;
} 

二、LeetCode: 42. 接雨水

(1)问题描述

        

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 1:

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
示例 2:

输入:height = [4,2,0,3,2,5]
输出:9
 

提示:

n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105

(2)代码实现

        

class Solution {
    public int trap(int[] height) {
        int n=height.length;
        if(n==0) return 0;
        int[] leftMax=new int[n];
        leftMax[0]=height[0];
        for(int i=1;i<n;i++){
            leftMax[i]=Math.max(height[i],leftMax[i-1]);
        }
        int[] rightMax=new int[n];
        rightMax[n-1]=height[n-1];
        for(int i=n-2;i>=0;i--){
            rightMax[i]=Math.max(rightMax[i+1],height[i]);
        }
        int ans=0;
        for(int i=0;i<n;i++){
            ans+=Math.min(leftMax[i],rightMax[i])-height[i];
        }
        return ans;
    }
}

三、LeetCode: 2091. 从数组中移除最大值和最小值

(1)问题描述

        

给你一个下标从 0 开始的数组 nums ,数组由若干 互不相同 的整数组成。

nums 中有一个值最小的元素和一个值最大的元素。分别称为 最小值 和 最大值 。你的目标是从数组中移除这两个元素。

一次 删除 操作定义为从数组的 前面 移除一个元素或从数组的 后面 移除一个元素。

返回将数组中最小值和最大值 都 移除需要的最小删除次数。

示例 1:

输入:nums = [2,10,7,5,4,1,8,6]
输出:5
解释:
数组中的最小元素是 nums[5] ,值为 1 。
数组中的最大元素是 nums[1] ,值为 10 。
将最大值和最小值都移除需要从数组前面移除 2 个元素,从数组后面移除 3 个元素。
结果是 2 + 3 = 5 ,这是所有可能情况中的最小删除次数。
示例 2:

输入:nums = [0,-4,19,1,8,-2,-3,5]
输出:3
解释:
数组中的最小元素是 nums[1] ,值为 -4 。
数组中的最大元素是 nums[2] ,值为 19 。
将最大值和最小值都移除需要从数组前面移除 3 个元素。
结果是 3 ,这是所有可能情况中的最小删除次数。 
示例 3:

输入:nums = [101]
输出:1
解释:
数组中只有这一个元素,那么它既是数组中的最小值又是数组中的最大值。
移除它只需要 1 次删除操作。
 

提示:

1 <= nums.length <= 105
-105 <= nums[i] <= 105
nums 中的整数 互不相同

(2)代码实现

        

class Solution {
    public int minimumDeletions(int[] nums) {
         int maxIdx=0,minIdx=0;
         for(int i=0;i<nums.length;i++){
             maxIdx=nums[i]>nums[maxIdx]? i:maxIdx;
             minIdx=nums[i]<nums[minIdx]? i:minIdx;
         }
         int front=Math.max(maxIdx,minIdx)+1;
         int back=Math.max(nums.length-maxIdx,nums.length-minIdx);
         int f_b=(Math.min(maxIdx,minIdx)+1)+(nums.length-Math.max(maxIdx,minIdx));
         return Math.min(Math.min(front, back), f_b);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值