小明刚刚入职淘宝,老大给他交代了一个简单的任务,实现一个简易的商品推荐系统。
这个商品推荐系统的需求如下:
一共有 nn 件商品可以被推荐,他们的编号分别为 11 到 nn。每件商品都有一个价格,编号为 ii的商品价格为 p_ipi 元。现在需要给用户推荐尽可能多的商品,但是要保证按照编号上升的顺序给用户依次推荐商品,并且,相邻商品的价格之差的绝对值不能超过 dd。注意,第一个推荐的商品价格没有限制。
输入格式
第一行输入一个整数 TT,表示测试数据组数。
接下来依次输入 TT 组数据,每组数据按照下面的格式输入:
第一行输入两个整数 nn 和 dd,意义如题目描述所示。
接下来一行输入 nn 个整数,第 ii 个整数表示 p_ipi。
保证 1 \lt T \le 501<T≤50, 1 \le n \le 300001≤n≤30000, 0 \le d \le 1000≤d≤100, 1 \le p_i \le 10^51≤pi≤105。
保证 \sum n \le 6*10^5∑n≤6∗105。
输出格式
对于每组数据,输出一行一个整数,表示最多能推荐的商品个数。
样例输入
2 6 3 5 7 3 6 10 9 8 6 4 7 9 5 8 1 9 10
样例输出
4 7
思路:没什么说的了,一眼DP,看代码把
ps:如果d = 1e5 可以用线段树优化,具体还没仔细想 等着补一下
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1e5 + 5;
int dp[maxn], pri[maxn];
int main()
{
int t, n, d, x;
cin >> t;
while(t--)
{
memset(dp, 0, sizeof(dp));
scanf("%d%d",&n, &d);
for(int i = 1; i <= n; i++)
scanf("%d", &pri[i]);
int ans = -1;
for(int i = 1; i <= n; i++)
{
int v = pri[i];
dp[v]++;
for(int k = -d; k <= d; k++)
{
int pre = v + k;
if(pre >= 1 && pre < maxn && dp[pre] && pre != v)
{
dp[v] = max(dp[v], dp[pre]+1);
// printf("%d %d %d\n", v, pre, dp[v]);
}
}
ans = max(ans, dp[v]);
}
printf("%d\n", ans);
}
return 0;
}
阿里巴巴的手机代理商正在研究 infra 输入法的新功能。他们需要分析单词频率以改进用户输入法的体验。于是需要你在系统内核里面写一个 API。 API 有如下功能:
添加操作
添加操作格式为
insert barty 8
,意思为插入barty
这个单词,这个单词词频为 88次。注意如果再次添加insert barty 8
操作时,就会将词频增加为 1616 次。(不会出现词频 \le 0≤0 的情况)。删除操作
删除操作格式为
delete barty
,意思为删除所有barty
这个单词。如果当前没有删除的词汇,输出
Empty
。查询操作
查询操作格式为
query ty
,意思为查询当前版本以ty
结尾的单词词频总和。
输入格式
第一行读入一个整数 TT,代表数据组数。
每组数据的第一行读入一个整数 NN 代表操作数。
接下来 NN 行,每行形容一个操作。
保证数据满足 1 \le T \le 101≤T≤10,1 \le N \le 10001≤N≤1000,insert
操作的字符串总长度之和 \le 3000≤3000,所有字符串长度 \le 10000≤10000,输入只有小写字母。
输出格式
输出题目中要求的结果。
样例输入
1 6 insert barty 8 query ty insert party 9 query ty delete barty query ty
样例输出
8 17 9
思路:倒序字典树
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 1e4 + 7;
int id, ch[maxn][30], cnt[maxn];
char cmd[maxn], str[maxn];
void Insert(char *s, int v)
{
int rt = 0;
int len = strlen(s);
for(int i = len-1; i >= 0; i--)
{
if(!ch[rt][s[i]-'a'])
{
memset(ch[id], 0, sizeof(ch[id]));
cnt[id] = 0;
ch[rt][s[i]-'a'] = id++;
}
rt = ch[rt][s[i]-'a'];
cnt[rt] += v;
}
}
void Delete(char *s, int v)
{
int rt = 0, flag = 0;
int len = strlen(s);
rt = 0;
for(int i = len-1; i >= 0; i--)
{
rt = ch[rt][s[i]-'a'];
cnt[rt] -= v;
}
}
int match(char *s)
{
int rt = 0;
int len = strlen(s);
for(int i = len-1; i >= 0; i--)
{
if(!ch[rt][s[i]-'a'])
return 0;
rt = ch[rt][s[i]-'a'];
}
return cnt[rt];
}
int main()
{
int t;
cin >> t;
while(t--)
{
map<string, int> mp;
id = 1;
memset(ch[0], 0, sizeof(ch[0]));
int n, x;
scanf("%d", &n);
while(n--)
{
scanf(" %s", cmd);
if(cmd[0] == 'i')
{
scanf(" %s", str);
scanf("%d", &x);
// cout << str << ' ' << x << endl;
mp[str] += x;
Insert(str, x);
}
else if(cmd[0] == 'd')
{
scanf(" %s", str);
if(mp[str] == 0)
printf("Empty\n");
else
{
Delete(str, mp[str]);
mp[str] = 0;
}
}
else
{
scanf(" %s", str);
printf("%d\n", match(str));
}
}
}
return 0;
}