HZOI String STL的正確用法
String 3s 512 MB
描述
硬盤中裏面有n個文件,文件從1到n標號,每個文件可以用若幹個數字序列來表示,而且每個文件存在一個重要值。現在請你完成一個搜索系統,有m
個搜索的操作,如果一個文件中有以這個數字序列為前綴的數字序列,那麽這個文件會被搜索到,現在我們想知道會有多少個文件被搜索到,以及這
些文件中重要值前k小的是哪些。
輸入
第一行兩個數n,m。
接下來n行是對每個文件的描述(標號依次是1到n):
每行的前兩個數字分別為描述這個文件的數字序列個數t和文件的重要值v。
接下來有t組數。
每組數先有一個數l,表示這個數字序列的長度。
接下來有l個數,表示這個序列。
接下來m行表示m個搜索操作:
每行的前兩個數字分別為搜索數k和前綴長度l。
接下來l個數是這個前綴的數字序列。
輸出
共m行。
每行來表示搜索的結果:
首先你需要輸出有多少個文件會被搜索到。
接下來你需要輸出k個數,依次是重要值前k小的標號(根據重要值由小到大輸出,重要值相同時,標號小的排在前面)。
如果搜索到的文件數p比k小,那麽你只需要輸出p個,如果沒有搜索到文件就不用輸出了。
樣例輸入
5 5
1 1 5 1 2 3 4 5
1 2 5 1 2 4 5 3
1 8 5 2 1 4 3 2
1 9 5 2 1 8 5 2
1 1 5 1 2 3 4 5
2 2 1 2
3 2 1 2
4 2 1 2
4 2 2 1
1 2 2 1
樣例輸出
3 1 5
3 1 5 2
3 1 5 2
2 3 4
2 3
n,m<=50000,插入長度和與詢問長度和<=200000
這道題很明顯是個trie,但是數那麽大不好定義兒子,我們可以在每個文件裏建一棵trie但是這樣的話總時間為10^10,行不通,那麽我們就建一棵全局的trie我們把每個點都在其經過路徑上放進去那麽只會插入200000個點,而且開出來的trie點也不會超過200000,這樣時間復雜度是200000,至於把每個數拆開,出題人說太麻煩......
這樣的話我們可以直接把map當兒子,把set當節點儲存,對於set,它裏面有一個內置的東西是一個結束標誌,就是在end()的時候輸出的那個,當裏面沒有元素的的時候begin()就和end()一樣了,那其實應該是個標記指針,對於pair要調iostream他有自動的先按第一關鍵字再按第二關鍵字的排序性質,而且它可以當做一種變量。
對於動態的trie來說,指針確實不太好打。
#include<set> #include<iostream> #include<map> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define MAXN 200050 using namespace std; typedef pair<int,int> p; set<p> s[MAXN]; set<p>::iterator it; map<int,int>ch[MAXN]; inline int read() { int SUM=0; char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { SUM=(SUM<<1)+(SUM<<3)+ch-‘0‘; ch=getchar(); } return SUM; } int n,m,tot=1; inline void insert(p x) { int l=read(); int now=1; while(l--) { int y=read(); if(!ch[now].count(y))ch[now][y]=++tot; now=ch[now][y]; s[now].insert(x); } } int need[MAXN]; int main() { freopen("string.in","r",stdin); freopen("string.out","w",stdout); n=read(); m=read(); for(int i=1;i<=n;i++) { int t=read(),v=read(); for(int j=1;j<=t;j++) insert(make_pair(v,i)); } for(int i=1;i<=m;i++) { int k=read(),l=read(),now=1; for(int j=1;j<=l;j++)need[j]=read(); int j; for(j=1;j<=l&&ch[now].count(need[j]);j++) now=ch[now][need[j]]; if(j<=l)now=0; printf("%d ",s[now].size()); if(k>s[now].size())k=s[now].size(); for(j=1,it=s[now].begin();j<=k;++it,j++) printf("%d ",it->second); printf("\n"); } return 0; }
HZOI String STL的正確用法