1. 程式人生 > >HZOI String STL的正確用法

HZOI String STL的正確用法

結束 clas stdout insert space cond def gin --

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的正確用法