当前位置: 代码迷 >> 综合 >> 【洛谷】P2058:海港
  详细解决方案

【洛谷】P2058:海港

热度:72   发布时间:2024-03-09 01:24:01.0

传送门 

上一篇怎么说的来着?

高产期开始!!!

然后就一年多没更。

唉,打脸了。

话不多说,开始讲今天的题目吧 。

海港

题目描述

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

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

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

形式化地讲,你需要计算nn条信息。对于输出的第ii条信息,你需要统计满足ti??86400<tp?≤ti?的船只pp,在所有的xp,j?中,总共有多少个不同的数。

输入格式

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

接下来n行,每行描述一艘船的信息:前两个整数ti?ki?分别表示这艘船到达海港的时间和船上的乘客数量,接下来ki?个整数xi,j?表示船上乘客的国籍。

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

这是一道经典的普及组题目,由于现在在备战CSP,我就把这道题做了一遍。

首先,Read()和write()走起:


inline int Read()
{int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();return s*w;
}
void write(int n)
{if(n==0)return;write(n/10);putchar(n%10+'0');
}

一条船到了,上面有不同国籍的乘客,而24小时后,他们就会跟不上时代的步伐不再被计算。

很明显——先进先出,队列!

于是我用queue写了起来(虽然我已经完全不会写queue了)。

最后得了40分(我把queue当桶用了。。。第2个样例还过不了)。

40分代码:

#include<bits/stdc++.h>
using namespace std;
queue<long long>q;
long long n,t[1000010],k,barrel[1000010]={0};
void q_clear()
{while(q.front()<=9999999)q.pop();q.pop();
}
int main()
{int tmp,tot=0,minn=1;cin>>n;while(n--){memset(barrel,0,sizeof(barrel));cin>>t[++tot]>>k;while(k--){cin>>tmp;q.push(tmp);}//cout<<q.front()<<endl;q.push(t[tot]+10000000);while(t[minn]+86400-t[tot]<=0){minn++;q_clear();}int ans=0;for(int i=1;i<q.size();i++){barrel[q.front()]++;if(barrel[q.front()]==1)ans++;q.push(q.front());q.pop();}q.pop();cout<<ans<<endl;}return 0;
}

这个代码有RT,有TLE(为什么有TLE?因为代码还没来得及RT就TLE了)。

我很有自知之明,晓得自己写不出queue,便换了种思路。

然后我有了个大发现:

一条船上,相同国籍的人,不管再多,时间到了,他们就都会跟不上时代的步伐不再被计算!

So,想要降低时间复杂度,只要在存每一条船时,每个国籍只记录1个,就行了!

要判重,要速度,怎么办?

Set!

于是我又敲起了代码,其实也就是用set优化了一下桶,结果跑得居然挺快!

然鹅WA了QAQ

40分:

#include<bits/stdc++.h>
using namespace std;
inline int Read()
{int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();return s*w;
}
void write(int n)
{if(n==0)return;write(n/10);putchar(n%10+'0');
}
set<long long>s[100010];
long long n,t[100010],k,x[100010]={0};
int main()
{int minn=1,ans=0;n=Read();for(int i=1;i<=n;i++){t[i]=Read();k=Read();while(k--){int tmp;tmp=Read();s[i].insert(tmp);}set<long long>::iterator it;for(it=s[i].begin();it!=s[i].end();it++){//cout<<*it<<" ";x[*it]++;if(x[*it]==1)ans++;}while(t[minn]+86400<=t[i]){set<long long>::iterator it;for(it=s[minn].begin();it!=s[minn].end();it++){x[*it]--;if(x[*it]==0)ans--;}minn++;//s[minn].clear();}write(ans);putchar('\n');//cout<<s[i].size()<<endl;}return 0;
}

我认真的思考为什么会WA。

然后把

while(t[minn]+86400<=t[i])

改成了

while(t[minn]+86400<t[i])

emm,这不符合题意,肯定改错了啊。

结果交上去,70分。

70分!

70分?

变多了?

于是我又有了希望,因为这数据

我把那段代码改回去,又细细端详了端详我的代码。

这时我才想到:

write有一个大坑点!

如果a=0,用write输出a,会是什么?

什么都不输出!

于是我赶紧把

write(ans);
putchar('\n');

改成了

if(ans==0)putchar('0');
elsewrite(ans);
putchar('\n');

又交了一遍,

AC!!!

附上AC代码:

#include<bits/stdc++.h>
using namespace std;
inline int Read()
{int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();return s*w;
}
void write(int n)
{if(n==0)return;write(n/10);putchar(n%10+'0');
}
set<long long>s[100010];
long long n,t[100010],k,x[100010]={0};
int main()
{int minn=1,ans=0;n=Read();for(int i=1;i<=n;i++){t[i]=Read();k=Read();while(k--){int tmp;tmp=Read();s[i].insert(tmp);}set<long long>::iterator it;for(it=s[i].begin();it!=s[i].end();it++){//cout<<*it<<" ";x[*it]++;if(x[*it]==1)ans++;}while(t[minn]+86400<=t[i]){set<long long>::iterator it;for(it=s[minn].begin();it!=s[minn].end();it++){x[*it]--;//cout<<x[*it]<<' ';if(x[*it]==0)ans--;}minn++;//s[minn].clear();}if(ans==0)putchar('0');elsewrite(ans);putchar('\n');//cout<<s[i].size()<<endl;}return 0;
}

以后还是要勤奋些~(每日立flag