ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2058 [NOIP2016 普及组] 海港

2022-08-24 22:01:39  阅读:174  来源: 互联网

标签:24 NOIP2016 cnt 10 海港 到达 leq P2058


# [NOIP2016 普及组] 海港

## 题目背景

NOIP2016 普及组 T3

## 题目描述

小 K 是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客。

小 K 对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况;对于第 $i$ 艘到达的船,他记录了这艘船到达的时间 $t_i$ (单位:秒),船上的乘客数 $k_i$,以及每名乘客的国籍 $x_{i,1}, x_{i,2},\dots,x_{i,k}$。

小K统计了 $n$ 艘船的信息,希望你帮忙计算出以每一艘船到达时间为止的 $24$ 小时($24$ 小时 $=86400$ 秒)内所有乘船到达的乘客来自多少个不同的国家。

形式化地讲,你需要计算 $n$ 条信息。对于输出的第 $i$ 条信息,你需要统计满足 $t_i-86400<t_p \le t_i$ 的船只 $p$,在所有的 $x_{p,j}$ 中,总共有多少个不同的数。

## 输入格式

第一行输入一个正整数 $n$,表示小 K 统计了 $n$ 艘船的信息。

接下来 $n$ 行,每行描述一艘船的信息:前两个整数 $t_i$ 和 $k_i$ 分别表示这艘船到达海港的时间和船上的乘客数量,接下来 $k_i$ 个整数 $x_{i,j}$ 表示船上乘客的国籍。

保证输入的 $t_i$ 是递增的,单位是秒;表示从小K第一次上班开始计时,这艘船在第 $t_i$ 秒到达海港。

保证 $1 \le n \le 10^5$,$\sum{k_i} \le 3\times 10^5 $ ,$1\le x_{i,j} \le 10^5$, $1 \le t_{i-1}\le t_i \le 10^9$。


其中 $\sum{k_i}$ 表示所有的 $k_i$ 的和。

## 输出格式

输出 $n$ 行,第 $i$ 行输出一个整数表示第 $i$ 艘船到达后的统计信息。

## 样例 #1

### 样例输入 #1

```
3
1 4 4 1 2 2
2 2 2 3
10 1 3
```

### 样例输出 #1

```
3
4
4
```

## 样例 #2

### 样例输入 #2

```
4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5
```

### 样例输出 #2

```
3
3
3
4
```

## 提示

【样例解释 1】

第一艘船在第 $1$ 秒到达海港,最近 $24$ 小时到达的船是第一艘船,共有 $4$ 个乘客,分别是来自国家 $4,1,2,2$,共来自 $3$ 个不同的国家;

第二艘船在第 $2$ 秒到达海港,最近 $24$ 小时到达的船是第一艘船和第二艘船,共有 $4 + 2 = 6$ 个乘客,分别是来自国家 $4,1,2,2,2,3$,共来自 $4$ 个不同的国家;

第三艘船在第 $10$ 秒到达海港,最近 $24$ 小时到达的船是第一艘船、第二艘船和第三艘船,共有 $4+2+1=7$ 个乘客,分别是来自国家 $4,1,2,2,2,3,3$,共来自 $4$ 个不同的国家。

【样例解释 2】

第一艘船在第 $1$ 秒到达海港,最近 $24$ 小时到达的船是第一艘船,共有 $4$ 个乘客,分别是来自国家 $1,2,2,3$,共来自 $3$ 个不同的国家。

第二艘船在第 $3$ 秒到达海港,最近 $24$ 小时到达的船是第一艘船和第二艘船,共有 $4+2=6$ 个乘客,分别是来自国家 $1,2,2,3,2,3$,共来自 $3$ 个不同的国家。

第三艘船在第 $86401$ 秒到达海港,最近 $24$ 小时到达的船是第二艘船和第三艘船,共有 $2+2=4$ 个乘客,分别是来自国家 $2,3,3,4$,共来自 $3$ 个不同的国家。

第四艘船在第 $86402$ 秒到达海港,最近 $24$ 小时到达的船是第二艘船、第三艘船和第四艘船,共有 $2+2+1=5$ 个乘客,分别是来自国家 $2,3,3,4,5$,共来自 $4$个 不同的国家。

【数据范围】

- 对于 $10\%$ 的测试点,$n=1,\sum k_i \leq 10,1 \leq x_{i,j} \leq 10, 1 \leq t_i \leq 10$。
- 对于 $20\%$ 的测试点,$1 \leq n \leq 10, \sum k_i \leq 100,1 \leq x_{i,j} \leq 100,1 \leq t_i \leq 32767$。
- 对于 $40\%$ 的测试点,$1 \leq n \leq 100, \sum k_i \leq 100,1 \leq x_{i,j} \leq 100,1 \leq t_i \leq 86400$。
- 对于 $70\%$ 的测试点,$1 \leq n \leq 1000, \sum k_i \leq 3000,1 \leq x_{i,j} \leq 1000,1 \leq t_i \leq 10^9$。
- 对于 $100\%$ 的测试点,$1 \leq n \leq 10^5,\sum k_i \leq 3\times 10^5, 1 \leq x_{i,j} \leq 10^5,1\leq t_i \leq 10^9$。

#思路:

这个问题做出例一不难,因为不考虑时间因素,如果做出例一的话就有40分了(洛谷),但是例二要做出来可能比较难(可能因为我比较拉),因为涉及到队列的出队入队,逻辑是用一个结构体队列进行存储,用一个int数组标记船员的国家,如果这个国家被扫描到,那么这个位置就自增,用一个桶排序就可以了;如果当前下标的数组是1,就说明这个国家是第一次出现,那么cnt++,如果写到这里直接输出cnt和回车洛谷里是能拿到40分的,但是要满分还得费点劲

首先我们用创好的结构体声明一个变量,把当前船客的日期、国家记下来,然后放进结构体队列里,在for循环外面再用结构体声明两个变量,一个存最先的那一天(队首,之后还要进行pop操作),一个存最后的那一天(队尾),用这俩时间相减,如果差值≥86400,第一天标记的国家自减,因为要看看他第一天是否有独一无二的船员国籍,如果做过自减还不为0,说明他不是唯一的,直接出队,然后更新第一天的值,队首指标后移到第二天继续判断,直到这一天和最后一天在24小时内;如果做过自减后变为了0,说明他是独一无二的,那么cnt需要自减,因为第一天和最后一天不在24小时内,所以这个国籍不算数。

#代码:

 1 #include<iostream>
 2 #include<queue>
 3 using namespace std;
 4 //创建结构体
 5 struct ship{
 6     int time;
 7     int guo;
 8 };
 9 //创建结构体队列a
10 queue <ship> a;
11 //我不知道为什么b数组要开那么大,可能是做完上一题的后遗症
12 //c是输入国籍的临时变量
13 int b[300001],c;
14 int main(){
15     int n;
16     //cnt存储国籍数目
17     int cnt=0;
18     cin>>n;
19     for(int i=1;i<=n;i++){//循环开始
20         int second,Number;
21         //变量名很随便不要介意啊,second是时间,Number是人数
22         cin>>second>>Number;
23         for(int d=1;d<=Number;d++){//每个人的国籍都要输入一次
24             cin>>c;
25             b[c]++;//桶排序
26             if(b[c]==1){//如果是首个标记的国籍,cnt++
27                 cnt++;
28             }
29             //用e来存当前船员的国籍和时间,然后放进队列a里面
30             ship e;
31             e.time=second;
32             e.guo=c;
33             a.push(e);
34         }
35         //刚刚是在for循环里创的e,for循环外面还是可以用e这个名字的
36         //用e和u存队首/队尾
37         ship e,u;
38         e=a.front();
39         u=a.back();
40         //如果不在同一天,那么差值一定大于等于86400,要注意的是题目中只要 *24小时内* 的国籍数
41         //所以我们的循环条件是>=,我写的时候就是因为这里没能AC,如果少了等于号洛谷给70分
42         while(u.time-e.time>=86400){
43             //队首的国籍自减
44             b[e.guo]--;
45             //如果为0说明是唯一的国籍,cnt自减
46             if(b[e.guo]==0){
47                 cnt--;
48             }
49             //队首出队
50             a.pop();
51             //更新e的值
52             e=a.front();
53         }
54         //这一艘船处理完了,输出国籍数目
55         cout<<cnt<<endl;
56     }
57     return 0;
58 }

 

可能写的不好,也可能和别人代码重复,因为这个代码老师有指点过我的思路…… 

标签:24,NOIP2016,cnt,10,海港,到达,leq,P2058
来源: https://www.cnblogs.com/Ghost1GM/p/16622390.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有