分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
973 字
5 分钟
String STL set map Trie
描述
硬盘中里面有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
数据范围和约定
- 对于20%的数据
0<n,m<=50
每次询问k无限制
0<重要值<=10^9
0<数字序列中的数字<=10
所有文件数字序列长度之和<=500
所有询问前缀数字序列长度之和<=500 - 对于另外20%的数据
0<n,m<=50
每次询问k无限制
0<重要值<=10^9
0<数字序列中的数字<=10^9
所有文件数字序列长度之和<=500
所有询问前缀数字序列长度之和<=500 - 对于另外20%的数据
0<n,m<=510^4
每次询问k=1或k=2
0<重要值<=10^9
0<数字序列中的数字<=10
所有文件数字序列长度之和<=210^5
所有询问前缀数字序列长度之和<=2*10^5 - 对于剩下的数据
0<n,m<=510^4
每次询问k无限制
0<重要值<=10^9
0<数字序列中的数字<=10^9
所有文件数字序列长度之和<=210^5
所有询问前缀数字序列长度之和<=2*10^5
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <ctime>
using namespace std;
vector<int> l;
struct Improtant
{
int i, Imp;
bool operator<(const Improtant &a) const
{
return Imp == a.Imp ? i < a.i : Imp < a.Imp;
}
} number[50005];
struct Trie
{
map<int, Trie *> mp;
set<Improtant> mark;
} * root;
void insert(int x)
{
Trie *rt = root;
rt->mark.insert(number[x]);
for (int i = 0; i < l.size(); i++)
{
if (!rt->mp[l[i]])
rt->mp[l[i]] = new Trie;
rt = rt->mp[l[i]];
rt->mark.insert(number[x]);
}
}
void Query(int k)
{
Trie *rt = root;
for (int i = 0; i < l.size(); i++)
{
if (rt->mp[l[i]] == NULL)
{
printf("0\n");
return;
}
rt = rt->mp[l[i]];
}
set<Improtant>::iterator it = rt->mark.begin();
printf("%d ", rt->mark.size());
for (int i = 1; i <= k && it != rt->mark.end(); i++, it++)
{
printf("%d ", it->i);
}
printf("\n");
return;
}
int main()
{
#ifdef Mine
freopen("1.in", "r", stdin);
#else
freopen("string.in", "r", stdin);
#endif
freopen("string.out", "w", stdout);
int n, m;
root = new Trie;
scanf("%d%d", &n, &m);
int t, s, a;
for (int i = 1; i <= n; i++)
{
number[i].i = i;
scanf("%d%d", &t, &number[i].Imp);
while (t--)
{
scanf("%d", &s);
l.clear();
for (int j = 1; j <= s; j++)
{
scanf("%d", &a);
l.push_back(a);
}
insert(i);
}
}
int k;
for (int i = 1; i <= m; i++)
{
scanf("%d%d", &k, &s);
l.clear();
for (int j = 1; j <= s; j++)
{
scanf("%d", &a);
l.push_back(a);
}
Query(k);
}
//printf("%lf",(double)clock()/CLOCKS_PER_SEC);
}