洛谷——P2058 海港

题目传送

 

  由于于题目保证输入的ti是递增的,所以发现当我们统计完一艘船的答案后,这个答案多少会对下一艘船的答案有贡献。同时还发现如果对每个艘船都记录他的乘客在整个数据出现的所有国籍中相应出现的次数,在这道题的范围下,显然会爆空间,其实这个题如果按照一般的静态数组存储的话,光是记录每个船的乘客就会爆空间,但其实乘客总数是很少的,只是每艘船上的乘客人数不确定,要想建数组存下这些数据,必须对每个船都要考虑载最多乘客的情况,就导致了很大的空间浪费,由此我们可以用动态数组来完美避免这个问题。

  综上,可以只建一个记录所有国籍出现次数的数组,下一艘船的答案只要从上一艘船的答案里从最早的开始往后找,找到第一个包括在这艘船答案里的船。对于之前寻找过程找过但不符合条件的船,要让他更新以下当前的国籍数组。最后别忘了把这艘船自己包括进他自己的答案里就行。这样只要我们把数据输入后对每艘船额外维护一个他的答案里最早的船的编号就行了。

见AC代码:

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 int *a[100001],n,k,ans,t[100001],nat[100001],len[100001];
 8 
 9 char ch;
10 
11 inline int read()
12 {
13     ans=0;
14     ch=getchar();
15     while(!isdigit(ch)) ch=getchar();
16     while(isdigit(ch)) ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
17     return ans;
18 }
19 
20 int main()
21 {
22     n=read();
23     for(int i=1;i<=n;i++)
24         {
25             t[i]=read();//每艘船的到来时间(注意以秒为单位
26             len[i]=read(); //乘客人数
27             a[i]=new int[len[i]+1];//动态数组
28             for(int j=1;j<=len[i];j++)
29                 a[i][j]=read();
30         }
31     int lst=1;//上一艘船答案里时间最早的船的编号
32     ans=0;
33     for(int i=1;i<=len[1];i++)//对第一艘船这个边界情况特殊处理
34     {
35         if(nat[a[1][i]]==0) ans++;
36             nat[a[1][i]]++;
37     }
38     printf("%d\n",ans);
39     int lim;
40     for(int k=2;k<=n;k++)
41     {
42         for(int i=1;i<=len[k];i++)
43         {
44             if(nat[a[k][i]]==0) ans++;
45             nat[a[k][i]]++;
46         }
47         lim=t[k]-86400;//最低时间满足下限
48         while(t[lst]<=lim)//寻找过程
49         {
50             for(int i=1;i<=len[lst];i++)
51             {
52                 nat[a[lst][i]]--;
53                 if(nat[a[lst][i]]==0) ans--;
54             }    
55             lst++;
56         }    
57         printf("%d\n",ans);
58     }
59     return 0;
60 }

 

posted @ 2019-06-26 10:02  千叶繁华  阅读(225)  评论(0编辑  收藏  举报