其他分享
首页 > 其他分享> > 洛谷P2058 海港 题解

洛谷P2058 海港 题解

作者:互联网

P2058 海港

题面

P2058 海港

NOIP2016第三题

题解

这道题笨蛋就是开一个数组vis[i]表示国籍是i的有几个人,用一个ans来控制国家数,vis[i]减完后若为0就ans--,vis[i]为0时要加就ans++,每次输出ans即可,注意要用tail每次刷新距离当前时间24小时外的船只。于是我们很快就码好一个笨蛋代码

 

#include<bits/stdc++.h>
using namespace std;
int n,vis[1005],x,tail=1,ans,k[1005],a[1005][1005],t[1005];
int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        t[i]=read();
        k[i]=read();
        for(int j=1;j<=k[i];j++){
            a[i][j]=read();
            if(vis[a[i][j]]==0)ans++;
            vis[a[i][j]]++;
        }
        while(t[i]-t[tail]>=86400){
            for(int j=1;j<=k[tail];j++){
                vis[a[tail][j]]--;
                if(vis[a[tail][j]]==0)ans--;
            }
            tail++;
        }
        printf("%d\n",ans);
    }
    return 0;
} 

 

测评发现笨蛋代码只能拿70分,并不意外......

因为数组大小的原因,很多数据都RE了...数组暴了,我们自然而然的想到了用vector来优化内存。但效率肯定会有所下降。

下面附上vector的代码

#include<bits/stdc++.h>
using namespace std;
int n,vis[500005],x,tail,ans,k[300005],t[100005];
vector<int> a[100005];
int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        t[i]=read();
        k[i]=read();
        for(int j=1;j<=k[i];j++){
            x=read();
            if(vis[x]==0)ans++;
            vis[x]++;
            a[i].push_back(x);
        }
        while(t[i]-t[tail]>=86400){
            for(int j=0;j<k[tail];j++){
                vis[a[tail][j]]--;
                if(vis[a[tail][j]]==0)ans--;
            }
            tail++;
        }
        printf("%d\n",ans);
    }
    return 0;
} 

 

惊奇的是暴力vector竟然过了,2016的数据是真的水啊!

不求甚解的我当然不会满足与vector的。

通过观察我们发现t[i]是递增的,而且k的总数不超过300000,我们自然而然的就想到了队列来储存每个人的信息,就不用每个时间段都开300000的数组了,只要开一个结构体记下每个人的国籍和来到的时间,用hed和til来控制头和尾,再用笨蛋的方法处理即可啊

(PS:没想到这题这么水)

关于队列

队列其实就是一种数据结构 “栈”无需自己写,递归过程中会自动开系统栈 “队列”需要自己写,一般有两种方式:

  1. 用数组模拟实现队列
  2. 用STL中自带的queue(常数比priority_queue大很多,慎用)STL连接

题目中我是这么定义结构体的

struct node{
    int ti,xi;
}hep[300005];

ti表示来到的时间xi表示国籍

STL队列

定义      queue<int> q;
队列不空     while(!q.empty())
新元素入队   q.push(m);
取队首元素   q.front();
队首元素出队  q.pop();

附上我的完美代码哈哈哈哈哈哈哈

#include<bits/stdc++.h>
using namespace std;
struct node{
    int ti,xi;
}hep[300005];
int n,t,k,vis[100005],hed,til,ans,x;
int read(){
    int ret=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    return ret*f;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        t=read();
        k=read();
        for(int j=1;j<=k;j++){
            x=read();
            if(vis[x]==0)ans++;
            vis[x]++;
            hep[++til]=(node){t,x};
        }
        while(t-hep[hed].ti>=86400){
            vis[hep[hed].xi]--;
            if(vis[hep[hed].xi]==0)ans--;
            hed++;
        }
        printf("%d\n",ans);
    }
    return 0;
} 

是不是比vector快,快才是信仰。。。

最后请大家关注我呗,嘿嘿嘿。

 

标签:ch,洛谷,int,题解,ret,vis,ans,P2058,getchar
来源: https://www.cnblogs.com/booksBlog/p/10579747.html