传送门
上一篇怎么说的来着?
高产期开始!!!
然后就一年多没更。
唉,打脸了。
话不多说,开始讲今天的题目吧 。
海港
题目描述
小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;
}