2018 计算之道初赛第二场 阿里巴巴的手机代理商(困难)(反向可持久化Trie)
阿里巴巴的手机代理商(困难)
阿里巴巴的手机代理商正在研究 infra 输入法的新功能。他们需要分析单词频率以改进用户输入法的体验。于是需要你在系统内核里面写一个 API。 API 有如下功能:
添加操作
添加操作格式为
insert barty 8
,意思为插入barty
这个单词,这个单词词频为 88 次。注意如果再次添加insert barty 8
操作时,就会将词频增加为 1616 次。(不会出现词频 \le 0≤0 的情况)。删除操作
删除操作格式为
delete barty
,意思为删除所有barty
这个单词。如果当前没有删除的词汇,输出
Empty
并不计入版本号。查询操作
查询操作格式为
query ty
,意思为查询当前版本以ty
结尾的单词词频总和。修改操作
修改操作格式为
update ty tied
,意思为将所有结尾是ty
的单词更新为tied
结尾,比如barty
会变为bartied
。如果不存在以ty
结尾的单词,输出Empty
。如果已经存在以tied
结尾的单词,那么说明存在 conflict。不做合并,输出Conflict
并且不算做新版本。如果既不存在ty
结尾的单词,也已经存在以tied
结尾的单词,则输出Empty
。旧版本查询操作
将操作 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,insert
和update
操作的字符串总长度之和 \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
题目来源
因为找结尾嘛,所以我们反向存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)的更多相关文章
- 2019 计蒜之道 初赛 第二场 B. 百度AI小课堂-上升子序列(简单) ( 实现)
题目背景 91029102 年 99 月 22 日,百度在 X 市 XX 中学举办的第一场 AI 知识小课堂大获好评!同学们对矩阵的掌握非常棒. 今天的 AI 知识小课堂的第二场开讲啦.本场 AI ...
- 2019 计蒜之道 初赛 第二场 A 百度AI小课堂-矩阵问题 ( 等差数列求和公式)
题目背景 91029102 年 99 月 11 日,百度在 X 市 XX 中学举办了一场 AI 知识小课堂,本场 AI 知识小课堂老师教授了一些矩阵的相关知识,因为矩阵在 AI 人工智能中也有相当的 ...
- 2018 计蒜之道-初赛 第一场 A-百度无人车
百度一共制造了 nn 辆无人车,其中第 ii 辆车的重量为 a_i\ \mathrm{kg}ai kg. 由于车辆过重会增大轮胎的磨损程度,现在要给这 nn 辆车减轻重量.每将一辆车减轻 1\ \m ...
- 动态规划-hdoj-4832-百度之星2014初赛第二场
Chess Problem Description 小度和小良近期又迷上了下棋.棋盘一共同拥有N行M列,我们能够把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王 ...
- 计蒜之道 初赛第一场B 阿里天池的新任务(简单)
阿里“天池”竞赛平台近日推出了一个新的挑战任务:对于给定的一串 DNA 碱基序列 tt,判断它在另一个根据规则生成的 DNA 碱基序列 ss 中出现了多少次. 首先,定义一个序列 ww: \displ ...
- 2017 计蒜之道 初赛 第一场 A、B题
A题 阿里的新游戏 题目概述: 阿里九游开放平台近日上架了一款新的益智类游戏——成三棋.成三棋是我国非常古老的一个双人棋类游戏,其棋盘如下图所示: 成三棋的棋盘上有很多条线段,只能在线段交叉点上放入棋 ...
- 2014百度之星初赛第二场hdu 4831 Scenic Popularity
Scenic Popularity Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!
我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...
- hihocoder 微软编程之美2015 初赛 第二场(暴力+字典序+图论+思维算法)
题目1 : 扑克牌 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 一副不含王的扑克牌由52张牌组成,由红桃.黑桃.梅花.方块4组牌组成,每组13张不同的面值.现在给定52 ...
随机推荐
- js写弹窗
1.先来看弹窗的模样 点击“弹出窗口”后会弹出下面窗口 2.下面是实现弹出窗口的代码,其中引入的jquery一般自己有,没有的话可以从网上下载.tanchuang.js和tanchuang.css写在 ...
- 从INT_MAX和INT_MIN看补码
刷一道题的时候遇到INT_MAX和INT_MIN的问题,有些东西忘了,梳理一下. INT_MAX为2147483647,INT_MIN为-2147483648,为什么MIN的绝对值比MAX多1呢,因为 ...
- 59、有用过with statement吗?它的好处是什么?
python中的with语句是用来干嘛的?有什么作用? with语句的作用是通过某种方式简化异常处理,它是所谓的上下文管理器的一种 用法举例如下: with open('output.txt', 'w ...
- koa源码阅读[3]-koa-send与它的衍生(static)
koa源码阅读的第四篇,涉及到向接口请求方提供文件数据. 第一篇:koa源码阅读-0第二篇:koa源码阅读-1-koa与koa-compose第三篇:koa源码阅读-2-koa-router 处理静态 ...
- JS设计模式——2.初识接口
什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...
- ThinkPHP自定义错误页面、成功页面及异常页面
为什么会选择 ThinkPHP 呢?首先,作为一款国产PHP框架,文档肯定比国外那些框架要丰富的多,而且容易看懂:其次,ThinkPHP已经发展了七八年的时间了,相对来说已经比较成熟了:当然,最重要的 ...
- Thinkphp的SQL查询方式
一.普通查询方式 a.字符串$arr=$m->where("sex=0 and username='gege'")->find();b.数组$data['sex']=0 ...
- 在Linux(CentOS)中安装.netcore SDK
官方链接 :https://dotnet.microsoft.com/download/linux-package-manager/centos/sdk-current 可以直接根据官方链接,选择Li ...
- MD5做为文件名。机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能获取吧。
可以采用机器(电脑)唯一码 + 上传IP + 当前时间戳 + GUID ( + 随机数),然后MD5做为文件名.机器唯一码有电脑的CPU信息和MAC地址,这两个信息需要在linux或unix系统下才能 ...
- 模板为webpack的目录结构
目录结构 | -- build // 项目构建(webpack)相关代码 | |-- build.js // 生产环境构建代码 | |-- check-version.js // 检查node.npm ...