P3955 [NOIP2017 普及组] 图书管理员
2017NOIP直接寄
先挂一道普及组没AC的题
题目背景
NOIP2017 普及组 T2
题目描述
图书馆中每本书都有一个图书编码,可以用于快速检索图书,这个图书编码是一个正整数。 每位借书的读者手中有一个需求码,这个需求码也是一个正整数。如果一本书的图书编码恰好以读者的需求码结尾,那么这本书就是这位读者所需要的。 小 D 刚刚当上图书馆的管理员,她知道图书馆里所有书的图书编码,她请你帮她写一个程序,对于每一位读者,求出他所需要的书中图书编码最小的那本书,如果没有他需要的书,请输出−1−1。
输入格式
第一行,包含两个正整数 n,qn,q,以一个空格分开,分别代表图书馆里 书的数量和读者的数量。
接下来的 nn 行,每行包含一个正整数,代表图书馆里某本书的图书编码。
接下来的 qq 行,每行包含两个正整数,以一个空格分开,第一个正整数代表图书馆 里读者的需求码的长度,第二个正整数代表读者的需求码。
输出格式
qq 行,每行包含一个整数,如果存在第 ii 个读者所需要的书,则在第 ii 行输出第 ii 个读者所需要的书中图书编码最小的那本书的图书编码,否则输出−1−1。
输入输出样例
5 5 2123 1123 23 24 24 2 23 3 123 3 124 2 12 2 12
23 1123 -1 -1 -1
说明/提示
【数据规模与约定】
对于 20%20%的数据,1≤n≤21≤n≤2。
另有 20%20%的数据,q=1q=1。
另有 20%20%的数据,所有读者的需求码的长度均为 11。
另有 20%20%的数据,所有的图书编码按从小到大的顺序给出。
对于 100%100%的数据,1≤n≤1,000,1≤q≤1,0001≤n≤1,000,1≤q≤1,000,所有的图书编码和需求码均 不超过 10,000,00010,000,000。
模拟处理字符串
第一次30pts,在处理字符串的函数的位置出现了问题
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <climits> 6 using namespace std; 7 const int M = 1e3 + 5; 8 inline int read(){ 9 int x = 0,f = 1; 10 char ch = getchar(); 11 while(ch < '0' || ch > '9'){ 12 if(ch == '-') f = -1; 13 ch = getchar(); 14 } 15 while(ch >= '0' && ch <= '9'){ 16 x = x * 10 + ch - '0'; 17 ch = getchar(); 18 } 19 return x * f; 20 } 21 struct B{ 22 string s; 23 int len = s.size(); 24 }b[M]; 25 int n,q; 26 int cnt[M]; 27 int chk(int len,string s){ 28 int lmt = cnt[s[len - 1] - '0']; 29 int maxn = INT_MAX; 30 for(register int i(1);i <= n;i ++) { 31 if (lmt) { 32 if (b[i].s[b[i].len - 1] == s[len - 1]) { 33 lmt--; 34 if (b[i].s.find(s) == (b[i].len - len) && b[i].s.find(s) != string::npos) { 35 int model = atoi(b[i].s.c_str()); 36 maxn = min(maxn, model); 37 } 38 } 39 } 40 } 41 return maxn; 42 } 43 int main(){ 44 n = read(); 45 q = read(); 46 for(register int i(1);i <= n;i ++){cin>>b[i].s;cnt[b[i].s[b[i].s.size() - 1] - '0']++;b[i].len = b[i].s.size();} 47 for(register int i(1);i <= q;i ++){ 48 int len = read(); 49 string S; 50 cin>>S; 51 int ans = chk(len,S); 52 if(ans != INT_MAX) printf("%d\n",ans); 53 else cout << -1 << endl; 54 } 55 return 0; 56 }
第一遍检查的时候 感觉在计算所检查字符在字符串内的下标的时侯有问题 所以从头查下标
后来想到一个问题 有可能 模式串是主串内不唯一子串
例如 23 在 923608023 中 出现了两次
用STL string.find()从头开始搜可能就会出现错误
然后就换了string.rfind()凑后面开始反着搜
切
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <climits> 6 using namespace std; 7 const int M = 1e3 + 5; 8 inline int read(){ 9 int x = 0,f = 1; 10 char ch = getchar(); 11 while(ch < '0' || ch > '9'){ 12 if(ch == '-') f = -1; 13 ch = getchar(); 14 } 15 while(ch >= '0' && ch <= '9'){ 16 x = x * 10 + ch - '0'; 17 ch = getchar(); 18 } 19 return x * f; 20 } 21 struct B{ 22 string s; 23 int len = s.size(); 24 }b[M]; 25 int n,q; 26 int cnt[M]; 27 int chk(int len,string s){ 28 int lmt = cnt[s[len - 1] - '0']; 29 int maxn = INT_MAX; 30 for(register int i(1);i <= n;i ++) { 31 if (lmt) { 32 if (b[i].s[b[i].len - 1] == s[len - 1]) { 33 lmt--; 34 if (b[i].s.rfind(s) == (b[i].len - len) && b[i].s.find(s) != string::npos) { 35 int model = atoi(b[i].s.c_str()); 36 maxn = min(maxn, model); 37 } 38 } 39 } 40 } 41 return maxn; 42 } 43 int main(){ 44 n = read(); 45 q = read(); 46 for(register int i(1);i <= n;i ++){cin>>b[i].s;cnt[b[i].s[b[i].s.size() - 1] - '0']++;b[i].len = b[i].s.size();} 47 for(register int i(1);i <= q;i ++){ 48 int len = read(); 49 string S; 50 cin>>S; 51 int ans = chk(len,S); 52 if(ans != INT_MAX) printf("%d\n",ans); 53 else cout << -1 << endl; 54 } 55 return 0; 56 }
然后就是说
提高组的题全压在手里 样例都没过
棋盘 打搜 一直RE
队列 3月份写的 大暴力 一分没有 现在手里压着线段树
有个叫 时间复杂度 的大模拟 算了2个小时 打了快200行的模拟(个人换行贼多) 样例能过 但是t >= 20就跑不出来
宝藏 就 直接 贪心 + dfs 搜
然后就
卡
卡
卡
卡
卡
接着卡
然后
状压DP是什么(bushi
改了bfs (甚至还想套spfa后来给自己一个耳光就清醒了)
逛公园的话:
最短路计数(?)
套 dj 干
啊对对对 还是没过

浙公网安备 33010602011771号