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 ...
随机推荐
- matlab实现cart(回归分类树)
作为机器学习的小白和matlab的小白自己参照 python的 <机器学习实战> 写了一下分类回归树,这里记录一下. 关于决策树的基础概念就不过多介绍了,至于是分类还是回归..我说不清楚. ...
- 线程句柄和线程ID的区别
●CreateThread() API 用于创建线程. API 返回同时线程句柄,并通过参数得到线程标识符 (ID). 线程句柄有完全访问权创建线程对象. 运行线程时线程 ID 唯一标识线程在系统级别 ...
- centos 6.5配置ftp服务器,亲测可用
设置开机启动 1 chkconfig vsftpd on 启动服务 1 /sbin/service vsftpd start 配置FTP用户组/用户以及相应权限 添加用户组 1 groupadd ft ...
- [How to] HBase的bulkload使用方法
1.简介 将数据插入HBase表中的方法很多,我们可以通过TableOutputFormat以Mapreduce on HBase的方式将数据插入,也可以单纯的使用客户端API将数据插入.但是以上方法 ...
- ftp--vsftp\pureftpd
FTP是File Transfer Protocol(文件传输协议),用于Internet上的控制文件的双向传输. 现今常用在一个局域网内,如学校.公司等一个指定范围的区域.(因为太过于简单和不安全) ...
- cin关闭同步[转]
很多人会说cin的速度比scanf慢很多, 其实不然. cin慢的原因主要在于默认cin与stdin总是保持同步, 这一步是消耗时间大户. 只需要加上ios::sync_with_stdio(fals ...
- JAVA封装消息中间件调用一(kafka生产者篇)
这段时间因为工作关系一直在忙于消息中间件的发开,现在趁着项目收尾阶段分享下对kafka的一些使用心得. kafka的原理我这里就不做介绍了,可参考http://orchome.com/kafka/in ...
- Perl 连接Oracle 出现OCI missing的问题及解决
问题描述 新申请了一个虚拟机操作系统: Win Server 2008, 64位 , 8核, 16G Memory 上 http://www.activestate.com/activeperl 下载 ...
- windows 下 nginx 配置虚拟主机
1. 在 nginx 的配置文件 nginx.conf 里面 引入虚拟主机配置文件,以后所有的虚拟主机配置文件都在写这个文件里 include vhost.conf; (或者新建vhost ...
- Mybatis的核心配置
之前了解了Mybatis的基本用法,现在学习一下Mybatis框架中的核心对象以及映射文件和配置文件,来深入的了解这个框架. 1.Mybatis的核心对象 使用MyBatis框架时,主要涉及两个核心对 ...