1. 程式人生 > >POJ3320 尺取法的正確使用法

POJ3320 尺取法的正確使用法

vector 實踐 尺取 log 進度 童鞋 ini stream problem

一、前言及題意:

最近一直在找題訓練,想要更加系統的補補思維,補補漏洞什麽的,以避免被個類似於腦筋急轉彎的題目幹倒,於是在四處找書,找了紅書、藍書,似乎都有些不盡如人意。這兩天看到了日本人的白書,重新讀了一遍,其中若幹章節寫的非常務實也實踐起來相當實用,於是這就是白書上面一道推薦的題目,用於訓練尺取法的例題。考慮到最近老是讀錯題,所以就慢慢習慣於首先把個題目翻譯成中文之後在進行解讀:

傑西卡是個非常可愛的女孩子,因而有若幹男孩子追她,最近他的考試要到了,她需要花相當多部分的時間在這件事情上面,吐過他想通過考試,那麽她就必須把所有的只是點都熟悉透,但是寫教科書的人似乎十分在意一些奇怪的東西,於是他將將有的知道hisIan重復了若幹次。傑西卡童鞋希望知道她最少需要看多少頁連續的書才能夠完成她的復習進度。一個愛慕她的男孩子已經把每一頁的知識點使用獨立的編號標示了出來,但是他並不能夠很好的完成這個統計工作,所以你收到的聘用。

鏈接:https://vjudge.net/problem/POJ-3320

二、做法:

傳統意義上如果我們要枚舉連續的片段將會幾乎必然花費N2的時間來進行這個枚舉,但是根據尺取法的思路,我們並沒有必要完全的枚舉每種集合(如果他們顯然不合理的的話),此時的思路是,首先設置一個遊標,使得遊標在慢慢往後移動這代表了整個區間的結束位置,沒到達一個點,將記錄該點在區間中的出現次數,如果之前沒有出現過,則應當給CNT變量加上1,如果此時cnt變量等於所有知識點的總數,則應開始移動開始端的遊標,每到一處則減少1.。

但是這道題有些坑:
1,及即使關了同步,cin也會因為太慢而超時。

2,因為輸入整個只有一行,所以關同步這個操作會使得scanf無法讀取到全部所有的數據。

於是註釋掉關同步的行,cin換成scanf就可以了。

詳見代碼:

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
#include<set>
#include<map>
using namespace
std; const long long MAXN=1000000+233; int arr[MAXN]; int numb[MAXN]; int cntt[MAXN]; int ans=MAXN; int n; set<int>s; void init() { cin>>n; int pp=0; for(int i=0;i<n;++i) { scanf("%d",&arr[i]); // cin>>arr[i]; if(!s.count(arr[i]))numb[pp++]=arr[i],s.insert(arr[i]); }sort(numb,numb+pp); int spos=-1;int cnt=0; for(int i=0;i<n;++i) { int pos=lower_bound(numb,numb+pp,arr[i])-numb; if(!cntt[pos])cnt++;cntt[pos]++; while(cnt==pp) { ans=min(ans,i-spos); spos++; int pos2=lower_bound(numb,numb+pp,arr[spos])-numb; cntt[pos2]--; if(!cntt[pos2])cnt--; } } cout<<ans<<"\n"; } int main() { // cin.sync_with_stdio(false); init(); return 0; }

POJ3320 尺取法的正確使用法