天天看点

2018 计蒜之道 初赛 第二场 A && B

小明刚刚入职淘宝,老大给他交代了一个简单的任务,实现一个简易的商品推荐系统。

这个商品推荐系统的需求如下:

一共有 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 有如下功能:

  1. 添加操作

    添加操作格式为

    insert barty 8

    ,意思为插入

    barty

    这个单词,这个单词词频为 88次。注意如果再次添加

    insert barty 8

    操作时,就会将词频增加为 1616 次。(不会出现词频 \le 0≤0 的情况)。
  2. 删除操作

    删除操作格式为

    delete barty

    ,意思为删除所有

    barty

    这个单词。

    如果当前没有删除的词汇,输出

    Empty

  3. 查询操作

    查询操作格式为

    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;
}
           

继续阅读