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

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

阿里巴巴的手机代理商正在研究 infra 输入法的新功能。他们需要分析单词频率以改进用户输入法的体验。于是需要你在系统内核里面写一个 API。 API 有如下功能:

  1. 添加操作

    添加操作格式为insert barty 8 ,意思为插入barty这个单词,这个单词词频为 88 次。注意如果再次添加insert barty 8操作时,就会将词频增加为 1616 次。(不会出现词频 \le 00 的情况)。

  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,意思为查询当前版本 -33的版本中,以ied为结尾的单词的词频和。保证 当前版本 -− 退回版本 \ge 00(00 号版本为空)。

输入格式

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

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

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

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

输出格式

输出题目中要求的结果。

样例说明

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。

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

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define mod 7
  5 #define LL long long
  6 #define INF 0x3f3f3f3f
  7 #define mp make_pair
  8 #define pb push_back
  9 #define mp make_pair
 10 #define fi first
 11 #define se second
 12 using namespace std;
 13 const int N=1e6+10;
 14 struct node
 15 {
 16     int next[26];
 17     LL num,ende;
 18 }trie[3*N];
 19 stack<int> sta;
 20 set<int> used;
 21 int root[N],nowv,dt;
 22 int makenode()
 23 {
 24     int tot=sta.top();
 25     sta.pop();
 26     used.insert(tot);
 27     return tot;
 28 }
 29 int makenode(int i)
 30 {
 31     int tot=sta.top();
 32     sta.pop();
 33     used.insert(tot);
 34     trie[tot]=trie[i];
 35     return tot;
 36 }
 37 void delnode(int i)
 38 {
 39     used.erase(i);
 40     sta.push(i);
 41     return ;
 42 }
 43 char s[N],s2[N];
 44 void add(char *s,LL d,int &root)
 45 {
 46     root=makenode(root);
 47     int now=root,len=strlen(s),p;
 48     for(int i=len-1;i>=0;i--)
 49     {
 50         p=s[i]-'a';
 51         if(!trie[now].next[p])
 52             trie[now].next[p]=makenode();
 53         else
 54             trie[now].next[p]=makenode(trie[now].next[p]);
 55         now=trie[now].next[p];
 56         trie[now].num+=d;
 57     }
 58     trie[now].ende+=d;
 59     return ;
 60 }
 61 int pt[N];
 62 bool deleted(char *s,int &root)
 63 {
 64     root=makenode(root);
 65     LL d;
 66     int now=root,len=strlen(s),p;
 67     for(int i=len-1;i>=0;i--)
 68     {
 69         p=s[i]-'a';
 70         if(!trie[now].next[p])
 71             return false;
 72         now=trie[now].next[p];
 73     }
 74     if(trie[now].ende==0)
 75         return false;
 76     d=trie[now].ende;
 77     now=root;
 78     for(int i=len-1;i>=0;i--)
 79     {
 80         p=s[i]-'a';
 81         trie[now].next[p]=makenode(trie[now].next[p]);
 82         now=trie[now].next[p];
 83         trie[now].num-=d;
 84         pt[i]=now;
 85     }
 86     trie[now].ende=0;
 87     pt[len]=root;
 88     for(int i=0;i<len;i++)
 89     {
 90         if(trie[pt[i]].num>0)
 91             break;
 92         trie[pt[i+1]].next[s[i]-'a']=0;
 93         delnode(pt[i]);
 94     }
 95     return true;
 96 }
 97 LL query(char *s,int &root)
 98 {
 99     int now=root,len=strlen(s),p;
100     for(int i=len-1;i>=0;i--)
101     {
102         p=s[i]-'a';
103         if(!trie[now].next[p])
104             return 0;
105         now=trie[now].next[p];
106     }
107     return trie[now].num;
108 }
109 int update(char *s1,char *s2,int &root)
110 {
111     root=makenode(root);
112     int now=root,len=strlen(s1),p;
113     for(int i=len-1;i>=0;i--)
114     {
115         p=s1[i]-'a';
116         if(!trie[now].next[p])
117             return 1;
118         now=trie[now].next[p];
119     }
120     if(trie[now].num==0)
121         return 1;
122     LL d=trie[now].num;
123     now=root;
124     len=strlen(s2);
125     bool flag=0;
126     for(int i=len-1;i>=0;i--)
127     {
128         p=s2[i]-'a';
129         if(!trie[now].next[p])
130         {
131             flag=1;
132             break;
133         }
134         now=trie[now].next[p];
135     }
136     if(flag==0)
137         return 2;
138     now=root;
139     len=strlen(s1);
140     for(int i=len-1;i>0;i--)
141     {
142         p=s1[i]-'a';
143         trie[now].next[p]=makenode(trie[now].next[p]);
144         now=trie[now].next[p];
145         trie[now].num-=d;
146         pt[i]=now;
147     }
148     int pt1=trie[now].next[s1[0]-'a'];
149     trie[now].next[s1[0]-'a']=0;
150     pt[len]=root;
151     for(int i=1;i<len;i++)
152     {
153         if(trie[pt[i]].num>0)
154             break;
155         trie[pt[i+1]].next[s[i]-'a']=0;
156         delnode(pt[i]);
157     }
158     now=root;
159     len=strlen(s2);
160     for(int i=len-1;i>0;i--)
161     {
162         p=s2[i]-'a';
163         if(!trie[now].next[p])
164             trie[now].next[p]=makenode();
165         else
166             trie[now].next[p]=makenode(trie[now].next[p]);
167         now=trie[now].next[p];
168         trie[now].num+=d;
169     }
170     int pt2=now;
171     trie[pt2].next[s2[0]-'a']=pt1;
172     return 0;
173 }
174 int T,n,m;
175 LL d;
176 int main()
177 {
178     scanf("%d",&T);
179     for(int i=1;i<=3000000;i++)
180         sta.push(i);
181     while(T--)
182     {
183         root[0]=0;
184         nowv=0;
185         memset(&trie[0],0,sizeof(trie[0]));
186         scanf("%d",&n);
187         for(int i=1;i<=n;i++)
188         {
189             scanf("%s",s);
190             if(strcmp(s,"insert")==0)
191             {
192                 scanf("%s%lld",s,&d);
193                 ++nowv;
194                 add(s,d,root[nowv]=root[nowv-1]);
195             }
196             else if(strcmp(s,"delete")==0)
197             {
198                 scanf("%s",s);
199                 ++nowv;
200                 if(!deleted(s,root[nowv]=root[nowv-1]))
201                 {
202                     printf("Empty\n");
203                     nowv--;
204                 }
205 
206             }
207             else if(strcmp(s,"query")==0)
208             {
209                 scanf("%s",s);
210                 printf("%lld\n",query(s,root[nowv]));
211             }
212             else if(strcmp(s,"update")==0)
213             {
214                 scanf("%s%s",s,s2);
215                 nowv++;
216                 int k=update(s,s2,root[nowv]=root[nowv-1]);
217                 if(k==1)
218                 {
219                     printf("Empty\n");
220                     nowv--;
221                 }
222                 if(k==2)
223                 {
224                     printf("Conflict\n");
225                     nowv--;
226                 }
227             }
228             else if(strcmp(s,"vquery")==0)
229             {
230                 scanf("%s%d",s,&dt);
231                 printf("%lld\n",query(s,root[nowv-dt]));
232             }
233         }
234         for(auto p:used)
235         {
236             memset(&trie[p],0,sizeof(trie[p]));
237             sta.push(p);
238         }
239         used.clear();
240     }
241     return 0;
242 }
View Code

 

posted @ 2018-05-14 01:33  hk_lin  阅读(241)  评论(0编辑  收藏  举报