阿里巴巴的手机代理商(困难)

阿里巴巴的手机代理商正在研究 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结尾的单词词频总和。

  4. 修改操作

    修改操作格式为update ty tied,意思为将所有结尾是ty的单词更新为tied结尾,比如barty会变为bartied。如果不存在以ty结尾的单词,输出Empty。如果已经存在以tied结尾的单词,那么说明存在 conflict。不做合并,输出Conflict并且不算做新版本。如果既不存在ty结尾的单词,也已经存在以tied结尾的单词,则输出Empty

  5. 旧版本查询操作

    将操作 11,22,44 每次迭代更新都视为一个版本。版本间查询格式为vquery ied 3,意思为查询当前版本 -3−3的版本中,以ied为结尾的单词的词频和。保证 当前版本 -− 退回版本 \ge 0≥0(00 号版本为空)。

输入格式

第一行读入一个整数 TT,代表数据组数。

每组数据的第一行读入一个整数 NN 代表操作数。

接下来 NN 行,每行形容一个操作。

保证数据满足 1 \le T \le 101≤T≤10,1 \le N \le 10^51≤N≤105,insertupdate操作的字符串总长度之和 \le 10^6≤106,所有字符串长度 \le 10^6≤106,输入只有小写字母。

输出格式

输出题目中要求的结果。

样例说明

insert barty 8之后生成版本 11。

update ty tied之后生成版本 22。

insert party 9之后生成版本 33。

delete barty之后生成版本 44。

样例输入

1
10
insert barty 8
delete shawn
update ty tied
query tied
insert party 9
update y ed
query ty
delete party
vquery ied 2
vquery ed 1

样例输出

Empty
8
Conflict
9
8
8

题目来源

2018 计蒜之道 初赛 第二场


因为找结尾嘛,所以我们反向存string到Trie里,然后涉及多版本问题,怕空间不够用,写可持久化的时候加入了数组分配,拿个stack和set去动态分配。反正代码写完真长,debug一天2333。

被不成功不算更新版本坑了。。好气哦。。改一下就过了。

 #include<bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define mod 7
#define LL long long
#define INF 0x3f3f3f3f
#define mp make_pair
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=1e6+;
struct node
{
int next[];
LL num,ende;
}trie[*N];
stack<int> sta;
set<int> used;
int root[N],nowv,dt;
int makenode()
{
int tot=sta.top();
sta.pop();
used.insert(tot);
return tot;
}
int makenode(int i)
{
int tot=sta.top();
sta.pop();
used.insert(tot);
trie[tot]=trie[i];
return tot;
}
void delnode(int i)
{
used.erase(i);
sta.push(i);
return ;
}
char s[N],s2[N];
void add(char *s,LL d,int &root)
{
root=makenode(root);
int now=root,len=strlen(s),p;
for(int i=len-;i>=;i--)
{
p=s[i]-'a';
if(!trie[now].next[p])
trie[now].next[p]=makenode();
else
trie[now].next[p]=makenode(trie[now].next[p]);
now=trie[now].next[p];
trie[now].num+=d;
}
trie[now].ende+=d;
return ;
}
int pt[N];
bool deleted(char *s,int &root)
{
root=makenode(root);
LL d;
int now=root,len=strlen(s),p;
for(int i=len-;i>=;i--)
{
p=s[i]-'a';
if(!trie[now].next[p])
return false;
now=trie[now].next[p];
}
if(trie[now].ende==)
return false;
d=trie[now].ende;
now=root;
for(int i=len-;i>=;i--)
{
p=s[i]-'a';
trie[now].next[p]=makenode(trie[now].next[p]);
now=trie[now].next[p];
trie[now].num-=d;
pt[i]=now;
}
trie[now].ende=;
pt[len]=root;
for(int i=;i<len;i++)
{
if(trie[pt[i]].num>)
break;
trie[pt[i+]].next[s[i]-'a']=;
delnode(pt[i]);
}
return true;
}
LL query(char *s,int &root)
{
int now=root,len=strlen(s),p;
for(int i=len-;i>=;i--)
{
p=s[i]-'a';
if(!trie[now].next[p])
return ;
now=trie[now].next[p];
}
return trie[now].num;
}
int update(char *s1,char *s2,int &root)
{
root=makenode(root);
int now=root,len=strlen(s1),p;
for(int i=len-;i>=;i--)
{
p=s1[i]-'a';
if(!trie[now].next[p])
return ;
now=trie[now].next[p];
}
if(trie[now].num==)
return ;
LL d=trie[now].num;
now=root;
len=strlen(s2);
bool flag=;
for(int i=len-;i>=;i--)
{
p=s2[i]-'a';
if(!trie[now].next[p])
{
flag=;
break;
}
now=trie[now].next[p];
}
if(flag==)
return ;
now=root;
len=strlen(s1);
for(int i=len-;i>;i--)
{
p=s1[i]-'a';
trie[now].next[p]=makenode(trie[now].next[p]);
now=trie[now].next[p];
trie[now].num-=d;
pt[i]=now;
}
int pt1=trie[now].next[s1[]-'a'];
trie[now].next[s1[]-'a']=;
pt[len]=root;
for(int i=;i<len;i++)
{
if(trie[pt[i]].num>)
break;
trie[pt[i+]].next[s[i]-'a']=;
delnode(pt[i]);
}
now=root;
len=strlen(s2);
for(int i=len-;i>;i--)
{
p=s2[i]-'a';
if(!trie[now].next[p])
trie[now].next[p]=makenode();
else
trie[now].next[p]=makenode(trie[now].next[p]);
now=trie[now].next[p];
trie[now].num+=d;
}
int pt2=now;
trie[pt2].next[s2[]-'a']=pt1;
return ;
}
int T,n,m;
LL d;
int main()
{
scanf("%d",&T);
for(int i=;i<=;i++)
sta.push(i);
while(T--)
{
root[]=;
nowv=;
memset(&trie[],,sizeof(trie[]));
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s);
if(strcmp(s,"insert")==)
{
scanf("%s%lld",s,&d);
++nowv;
add(s,d,root[nowv]=root[nowv-]);
}
else if(strcmp(s,"delete")==)
{
scanf("%s",s);
++nowv;
if(!deleted(s,root[nowv]=root[nowv-]))
{
printf("Empty\n");
nowv--;
} }
else if(strcmp(s,"query")==)
{
scanf("%s",s);
printf("%lld\n",query(s,root[nowv]));
}
else if(strcmp(s,"update")==)
{
scanf("%s%s",s,s2);
nowv++;
int k=update(s,s2,root[nowv]=root[nowv-]);
if(k==)
{
printf("Empty\n");
nowv--;
}
if(k==)
{
printf("Conflict\n");
nowv--;
}
}
else if(strcmp(s,"vquery")==)
{
scanf("%s%d",s,&dt);
printf("%lld\n",query(s,root[nowv-dt]));
}
}
for(auto p:used)
{
memset(&trie[p],,sizeof(trie[p]));
sta.push(p);
}
used.clear();
}
return ;
}

2018 计算之道初赛第二场 阿里巴巴的手机代理商(困难)(反向可持久化Trie)的更多相关文章

  1. 2019 计蒜之道 初赛 第二场 B. 百度AI小课堂-上升子序列(简单) ( 实现)

    题目背景 ​91029102 年 99 月 22 日,百度在 X 市 XX 中学举办的第一场 AI 知识小课堂大获好评!同学们对矩阵的掌握非常棒. 今天的 AI 知识小课堂的第二场开讲啦.本场 AI ...

  2. 2019 计蒜之道 初赛 第二场 A 百度AI小课堂-矩阵问题 ( 等差数列求和公式)

    题目背景 ​91029102 年 99 月 11 日,百度在 X 市 XX 中学举办了一场 AI 知识小课堂,本场 AI 知识小课堂老师教授了一些矩阵的相关知识,因为矩阵在 AI 人工智能中也有相当的 ...

  3. 2018 计蒜之道-初赛 第一场 A-百度无人车

    百度一共制造了 nn 辆无人车,其中第 ii 辆车的重量为 a_i\ \mathrm{kg}ai​ kg. 由于车辆过重会增大轮胎的磨损程度,现在要给这 nn 辆车减轻重量.每将一辆车减轻 1\ \m ...

  4. 动态规划-hdoj-4832-百度之星2014初赛第二场

    Chess Problem Description 小度和小良近期又迷上了下棋.棋盘一共同拥有N行M列,我们能够把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王 ...

  5. 计蒜之道 初赛第一场B 阿里天池的新任务(简单)

    阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 ss 中出现了多少次. 首先,定义一个序列 ww: \displ ...

  6. 2017 计蒜之道 初赛 第一场 A、B题

    A题 阿里的新游戏 题目概述: 阿里九游开放平台近日上架了一款新的益智类游戏——成三棋.成三棋是我国非常古老的一个双人棋类游戏,其棋盘如下图所示: 成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋 ...

  7. 2014百度之星初赛第二场hdu 4831 Scenic Popularity

    Scenic Popularity Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  8. 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!

    我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...

  9. hihocoder 微软编程之美2015 初赛 第二场(暴力+字典序+图论+思维算法)

    题目1 : 扑克牌 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 一副不含王的扑克牌由52张牌组成,由红桃.黑桃.梅花.方块4组牌组成,每组13张不同的面值.现在给定52 ...

随机推荐

  1. js写弹窗

    1.先来看弹窗的模样 点击“弹出窗口”后会弹出下面窗口 2.下面是实现弹出窗口的代码,其中引入的jquery一般自己有,没有的话可以从网上下载.tanchuang.js和tanchuang.css写在 ...

  2. 从INT_MAX和INT_MIN看补码

    刷一道题的时候遇到INT_MAX和INT_MIN的问题,有些东西忘了,梳理一下. INT_MAX为2147483647,INT_MIN为-2147483648,为什么MIN的绝对值比MAX多1呢,因为 ...

  3. 59、有用过with statement吗?它的好处是什么?

    python中的with语句是用来干嘛的?有什么作用? with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种 用法举例如下: with open('output.txt', 'w ...

  4. koa源码阅读[3]-koa-send与它的衍生(static)

    koa源码阅读的第四篇,涉及到向接口请求方提供文件数据. 第一篇:koa源码阅读-0第二篇:koa源码阅读-1-koa与koa-compose第三篇:koa源码阅读-2-koa-router 处理静态 ...

  5. JS设计模式——2.初识接口

    什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...

  6. ThinkPHP自定义错误页面、成功页面及异常页面

    为什么会选择 ThinkPHP 呢?首先,作为一款国产PHP框架,文档肯定比国外那些框架要丰富的多,而且容易看懂:其次,ThinkPHP已经发展了七八年的时间了,相对来说已经比较成熟了:当然,最重要的 ...

  7. Thinkphp的SQL查询方式

    一.普通查询方式 a.字符串$arr=$m->where("sex=0 and username='gege'")->find();b.数组$data['sex']=0 ...

  8. 在Linux(CentOS)中安装.netcore SDK

    官方链接 :https://dotnet.microsoft.com/download/linux-package-manager/centos/sdk-current 可以直接根据官方链接,选择Li ...

  9. MD5做为文件名。机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能获取吧。

    可以采用机器(电脑)唯一码 + 上传IP + 当前时间戳 + GUID ( + 随机数),然后MD5做为文件名.机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能 ...

  10. 模板为webpack的目录结构

    目录结构 | -- build // 项目构建(webpack)相关代码 | |-- build.js // 生产环境构建代码 | |-- check-version.js // 检查node.npm ...