1. 程式人生 > >洛谷P2058 海港 題解

洛谷P2058 海港 題解

col 每次 targe P20 names 過程 .cn 方式 log

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快,快才是信仰。。。

最後請大家關註我唄,嘿嘿嘿。

洛谷P2058 海港 題解