LINK:字符串



看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子。

期望得分10分。实际得分10分。

另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳。

期望得分10分。实际得分100分。

由此可以发现玄学的暴力非常的强大 可能这就是所谓的暴力出奇迹吧.

考虑离线:这样就可以把SAM给建出来了 进一步的 每次询问是查询子树和。

每次修改是单点修改 可以利用线段树维护dfs序就做完了。

不过其中存在细节 分裂的节点是影响答案的统计的。

怎么处理分裂的节点?注意到 分裂的节点和当前添加的节点权值无关。

如果对于分裂出来的新节点权值赋值为0 那么这样就不太行。

一个简单的想法 对于分裂出的节点 都拥有自己对应的权值 就行了。

不过这一点很难维护 因为之前的询问可能直接就询问到分裂的节点了。

仔细思考 对于分裂的节点来说 我们在其最初的节点被赋值的时候就把被分裂的节点给赋好值即可。

这样就需要在SAM的建立的时候 对每个节点再标记一个时间戳 然后分裂的时候 直接vector在这个时间戳上打好标记在最初节点赋值的时候一并修改就解决了刚才的问题即可。

难写!!!

  1. //#include<bits/stdc++.h>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<string>
  5. #include<cstring>
  6. #include<ctime>
  7. #include<cmath>
  8. #include<cstdlib>
  9. #include<cctype>
  10. #include<algorithm>
  11. #include<queue>
  12. #include<stack>
  13. #include<deque>
  14. #include<vector>
  15. #include<bitset>
  16. #include<list>
  17. #include<map>
  18. #include<set>
  19. #include<utility>
  20. #include<iomanip>
  21. #define RE register
  22. #define ll long long
  23. #define putl(x) printf("%lld\n",x)
  24. #define gt(x) scanf("%d",&x)
  25. #define put(x) printf("%d\n",x)
  26. #define get(x) x=read()
  27. #define rep(p,n,i) for(int i=p;i<=n;++i)
  28. #define vep(p,n,i) for(int i=p;i<n;++i)
  29. #define fep(n,p,i) for(int i=n;i>=p;--i)
  30. #define pii pari<int,int>
  31. #define mod 998244353
  32. #define f(i) t[i].fa
  33. #define pb push_back
  34. #define zz p<<1
  35. #define yy p<<1|1
  36. #define len(i) t[i].len
  37. using namespace std;
  38. char *fs,*ft,buf[1<<15];
  39. inline char getc()
  40. {
  41. return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
  42. }
  43. inline int read()
  44. {
  45. RE int x=0,f=1;RE char ch=getc();
  46. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
  47. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
  48. return x*f;
  49. }
  50. const int MAXN=500010,maxn=50010<<2;
  51. int T,m,n,last=1,cnt=1,mark,len,id,len1;ll ans;
  52. char a[maxn],b[MAXN];
  53. struct wy
  54. {
  55. int fa,len;
  56. int ch[26];
  57. }t[maxn];
  58. vector<int>g[maxn];
  59. int v[maxn],dfn[maxn],s[maxn],out[maxn],lin[maxn],ver[maxn],nex[maxn],pos[maxn],sj[maxn];
  60. ll sum[maxn<<2];
  61. inline void add(int x,int y)
  62. {
  63. ver[++len1]=y;
  64. nex[len1]=lin[x];
  65. lin[x]=len1;
  66. }
  67. inline void insert(int x)
  68. {
  69. int p=last;
  70. int np=last=++cnt;
  71. len(np)=len(p)+1;
  72. while(p&&!t[p].ch[x])
  73. {
  74. t[p].ch[x]=np;
  75. p=f(p);
  76. }
  77. if(!p)f(np)=1;
  78. else
  79. {
  80. int q=t[p].ch[x];
  81. if(len(q)==len(p)+1)f(np)=q;
  82. else
  83. {
  84. int nq=++cnt;
  85. t[nq]=t[q];
  86. len(nq)=len(p)+1;
  87. f(q)=f(np)=nq;
  88. while(p&&t[p].ch[x]==q)
  89. {
  90. t[p].ch[x]=nq;
  91. p=f(p);
  92. }
  93. }
  94. }
  95. }
  96. inline void insert1(int x,int id)
  97. {
  98. int p=last;
  99. int np=last=++cnt;
  100. len(np)=len(p)+1;sj[np]=id;
  101. while(p&&!t[p].ch[x])
  102. {
  103. t[p].ch[x]=np;
  104. p=f(p);
  105. }
  106. if(!p)f(np)=1;
  107. else
  108. {
  109. int q=t[p].ch[x];
  110. if(len(q)==len(p)+1)f(np)=q;
  111. else
  112. {
  113. int nq=++cnt;
  114. t[nq]=t[q];sj[nq]=sj[q];
  115. len(nq)=len(p)+1;
  116. g[sj[q]].pb(nq);
  117. g[sj[q]].pb(len(nq)-len(f(nq)));
  118. g[sj[q]].pb(q);
  119. g[sj[q]].pb(len(q)-len(nq)-(len(q)-len(f(q))));
  120. f(q)=f(np)=nq;
  121. while(p&&t[p].ch[x]==q)
  122. {
  123. t[p].ch[x]=nq;
  124. p=f(p);
  125. }
  126. }
  127. }
  128. g[id].pb(np);
  129. g[id].pb(len(np)-len(f(np)));
  130. }
  131. inline void dfs(int x)
  132. {
  133. ans+=len(x)-len(f(x));
  134. rep(1,cnt,i)if(f(i)==x)dfs(i);
  135. }
  136. inline void ask()
  137. {
  138. int now=1;
  139. rep(1,len,i)
  140. {
  141. if(!t[now].ch[b[i]-'a'])return ans=0,void();
  142. now=t[now].ch[b[i]-'a'];
  143. }
  144. ans=-(len-len(f(now))-1);
  145. dfs(now);
  146. }
  147. inline void build(int p,int l,int r)
  148. {
  149. if(l==r)
  150. {
  151. sum[p]=v[pos[l]];
  152. return;
  153. }
  154. int mid=(l+r)>>1;
  155. build(zz,l,mid);
  156. build(yy,mid+1,r);
  157. sum[p]=sum[zz]+sum[yy];
  158. }
  159. inline void change(int p,int l,int r,int x,int w)
  160. {
  161. if(l==r)
  162. {
  163. sum[p]+=w;
  164. return;
  165. }
  166. int mid=(l+r)>>1;
  167. if(x<=mid)change(zz,l,mid,x,w);
  168. else change(yy,mid+1,r,x,w);
  169. sum[p]=sum[zz]+sum[yy];
  170. }
  171. inline void dfs1(int x)
  172. {
  173. dfn[x]=++id;pos[id]=x;
  174. for(int i=lin[x];i;i=nex[i])
  175. {
  176. int tn=ver[i];
  177. dfs1(tn);
  178. }
  179. out[x]=id;
  180. }
  181. inline void change(int x,int w)
  182. {
  183. v[x]+=w;
  184. change(1,1,cnt,dfn[x],w);
  185. }
  186. inline ll ask(int p,int l,int r,int L,int R)
  187. {
  188. if(L<=l&&R>=r)return sum[p];
  189. int mid=(l+r)>>1;
  190. if(R<=mid)return ask(zz,l,mid,L,R);
  191. if(L>mid)return ask(yy,mid+1,r,L,R);
  192. return ask(zz,l,mid,L,R)+ask(yy,mid+1,r,L,R);
  193. }
  194. inline void ask(int x)
  195. {
  196. int now=1;ans=0;
  197. for(int i=0;i<g[x].size();++i)
  198. {
  199. if(!t[now].ch[g[x][i]])return;
  200. now=t[now].ch[g[x][i]];
  201. }
  202. if(!v[now])return;
  203. int w1=len(now);
  204. int w2=g[x].size();
  205. ans=-(w2-1-(len(f(now))+1)+1);
  206. ans+=ask(1,1,cnt,dfn[now],out[now]);
  207. }
  208. int main()
  209. {
  210. freopen("string.in","r",stdin);
  211. freopen("string.out","w",stdout);
  212. scanf("%s",a+1);n=strlen(a+1);
  213. fep(n,1,i)insert(a[i]-'a');
  214. rep(2,cnt,i)v[i]=len(i)-len(f(i));
  215. mark=cnt;
  216. gt(T);gt(m);
  217. if(m<=100)
  218. {
  219. rep(1,m,i)
  220. {
  221. int op;
  222. gt(op);
  223. if(!op)
  224. {
  225. scanf("%s",b+1);
  226. len=strlen(b+1);
  227. if(len>n){ans=0;put(0);}
  228. else
  229. {
  230. reverse(b+1,b+1+len);
  231. ask();putl(ans);
  232. }
  233. }
  234. else
  235. {
  236. scanf("%s",b+1);++n;
  237. int ww=(b[1]-'a'+ans*T)%26;
  238. insert(ww);
  239. }
  240. }
  241. return 0;
  242. }
  243. if(!T)
  244. {
  245. rep(1,m,i)
  246. {
  247. int op;gt(op);
  248. if(!op)
  249. {
  250. scanf("%s",b+1);
  251. len=strlen(b+1);
  252. reverse(b+1,b+1+len);
  253. rep(1,len,j)g[i].pb(b[j]-'a');
  254. s[i]=op;
  255. }
  256. else
  257. {
  258. scanf("%s",b+1);
  259. int ww=(b[1]-'a')%26;
  260. insert1(ww,i);
  261. s[i]=op;
  262. }
  263. }
  264. rep(2,cnt,i)add(f(i),i);
  265. dfs1(1);
  266. build(1,1,cnt);
  267. for(int i=0;i<g[0].size();i+=2)change(g[0][i],g[0][i+1]);
  268. rep(1,m,i)
  269. {
  270. if(s[i]==0)ask(i),putl(ans);
  271. else for(int j=0;j<g[i].size();j+=2)change(g[i][j],g[i][j+1]);
  272. }
  273. }
  274. return 0;
  275. }

期望得分 50.

这题不强制在线我都A了都。

考虑100分。

容易想到每次加入一个节点要实现断边 连边 维护子树和的功能。

上LCT 直接维护即可。这里不考虑维护子树和 而是每个点向上赋值 深度log咋做都对。

也不太好写 注意细节。

  1. //#include<bits/stdc++.h>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<string>
  5. #include<cstring>
  6. #include<ctime>
  7. #include<cmath>
  8. #include<cstdlib>
  9. #include<cctype>
  10. #include<algorithm>
  11. #include<queue>
  12. #include<stack>
  13. #include<deque>
  14. #include<vector>
  15. #include<bitset>
  16. #include<list>
  17. #include<map>
  18. #include<set>
  19. #include<utility>
  20. #include<iomanip>
  21. #define RE register
  22. #define ll long long
  23. #define putl(x) printf("%lld\n",x)
  24. #define gt(x) scanf("%d",&x)
  25. #define put(x) printf("%d\n",x)
  26. #define get(x) x=read()
  27. #define rep(p,n,i) for(int i=p;i<=n;++i)
  28. #define vep(p,n,i) for(int i=p;i<n;++i)
  29. #define fep(n,p,i) for(int i=n;i>=p;--i)
  30. #define pii pari<int,int>
  31. #define mod 998244353
  32. #define f(i) t[i].fa
  33. #define pb push_back
  34. #define zz p<<1
  35. #define yy p<<1|1
  36. #define len(i) t[i].len
  37. using namespace std;
  38. char *fs,*ft,buf[1<<15];
  39. inline char getc()
  40. {
  41. return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
  42. }
  43. inline int read()
  44. {
  45. RE int x=0,f=1;RE char ch=getc();
  46. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
  47. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
  48. return x*f;
  49. }
  50. const int MAXN=500010,maxn=50010<<2;
  51. int T,m,n,last=1,cnt=1,mark,len,id,len1;ll ans;
  52. char a[maxn],b[MAXN];
  53. struct wy{int fa,len;int ch[26];}t[maxn];
  54. struct LCT
  55. {
  56. #define l(x) c[x][0]
  57. #define r(x) c[x][1]
  58. int c[maxn][2],rev[maxn],s[maxn],fa[maxn];
  59. ll v[maxn],tag[maxn];
  60. inline bool pd(int x){return l(fa[x])==x||r(fa[x])==x;}
  61. inline void add(int x,ll y)
  62. {
  63. v[x]+=y;
  64. tag[x]+=y;
  65. }
  66. inline void rever(int x)
  67. {
  68. swap(l(x),r(x));
  69. rev[x]^=1;
  70. }
  71. inline void pushdown(int x)
  72. {
  73. if(rev[x])
  74. {
  75. rever(l(x));
  76. rever(r(x));
  77. rev[x]=0;
  78. }
  79. if(tag[x])
  80. {
  81. v[l(x)]+=tag[x];
  82. v[r(x)]+=tag[x];
  83. tag[l(x)]+=tag[x];
  84. tag[r(x)]+=tag[x];
  85. tag[x]=0;
  86. }
  87. }
  88. inline void rotate(int x)
  89. {
  90. int old=fa[x],oldf=fa[old],k=c[fa[x]][1]==x;
  91. c[old][k]=c[x][k^1];c[x][k^1]=old;
  92. if(pd(old))c[oldf][c[oldf][1]==old]=x;
  93. if(c[old][k])fa[c[old][k]]=old;
  94. fa[x]=oldf;fa[old]=x;
  95. }
  96. inline void splay(int x)
  97. {
  98. int top=0,y=x;
  99. s[++top]=x;
  100. while(pd(y))s[++top]=fa[y],y=fa[y];
  101. while(top)pushdown(s[top--]);
  102. while(pd(x))
  103. {
  104. int old=fa[x];
  105. if(pd(old))rotate(((c[old][0]==x)^(c[fa[old]][0]==old))?x:old);
  106. rotate(x);
  107. }
  108. }
  109. inline void access(int x)
  110. {
  111. for(int y=0;x;x=fa[y=x])
  112. splay(x),c[x][1]=y;
  113. }
  114. inline void make_root(int x)
  115. {
  116. access(x);
  117. splay(x);
  118. rever(x);
  119. }
  120. inline void LINK(int x,int y)
  121. {
  122. make_root(x);
  123. fa[x]=y;
  124. access(x);
  125. }
  126. inline void cutf(int x)
  127. {
  128. access(x);
  129. splay(x);
  130. fa[l(x)]=0;
  131. l(x)=0;
  132. }
  133. inline void cut(int x,int y)
  134. {
  135. make_root(x);
  136. cutf(y);
  137. }
  138. inline void change(int x,int p)
  139. {
  140. make_root(1);
  141. access(x);
  142. splay(x);
  143. add(x,p);
  144. }
  145. inline ll ask(int x)
  146. {
  147. access(x);
  148. splay(x);
  149. return v[x];
  150. }
  151. }R;
  152. inline void insert(int x)
  153. {
  154. int p=last;
  155. int np=last=++cnt;
  156. len(np)=len(p)+1;
  157. while(p&&!t[p].ch[x])
  158. {
  159. t[p].ch[x]=np;
  160. p=f(p);
  161. }
  162. if(!p)
  163. {
  164. f(np)=1;
  165. R.LINK(np,f(np));
  166. }
  167. else
  168. {
  169. int q=t[p].ch[x];
  170. if(len(q)==len(p)+1)
  171. {
  172. f(np)=q;
  173. R.LINK(np,f(np));
  174. }
  175. else
  176. {
  177. int nq=++cnt;
  178. R.change(q,-len(q)+len(f(q)));
  179. t[nq]=t[q];
  180. len(nq)=len(p)+1;
  181. R.LINK(nq,f(nq));
  182. R.v[nq]=R.ask(q);
  183. R.cut(q,f(q));
  184. R.LINK(np,nq);
  185. R.LINK(q,nq);
  186. f(q)=f(np)=nq;
  187. R.change(nq,len(nq)-len(f(nq)));
  188. R.change(q,len(q)-len(f(q)));
  189. while(p&&t[p].ch[x]==q)
  190. {
  191. t[p].ch[x]=nq;
  192. p=f(p);
  193. }
  194. }
  195. }
  196. R.change(np,len(np)-len(f(np)));
  197. }
  198. inline void ask()
  199. {
  200. ans=0;
  201. int now=1;
  202. fep(len,1,i)
  203. {
  204. if(!t[now].ch[b[i]-'a'])return ans=0,void();
  205. now=t[now].ch[b[i]-'a'];
  206. }
  207. ans=R.ask(now)-len+len(f(now))+1;
  208. }
  209. int main()
  210. {
  211. freopen("string.in","r",stdin);
  212. freopen("string.out","w",stdout);
  213. scanf("%s",a+1);n=strlen(a+1);
  214. fep(n,1,i)insert(a[i]-'a');
  215. gt(T);gt(m);
  216. rep(1,m,i)
  217. {
  218. int op;scanf("%d",&op);
  219. scanf("%s",b+1);
  220. if(!op)
  221. {
  222. len=strlen(b+1);
  223. ask();putl(ans);
  224. }
  225. else insert((b[1]-'a'+ans*T)%26);
  226. }
  227. return 0;
  228. }

6.18 省选模拟赛 字符串 LCT SAM的更多相关文章

  1. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  2. 6.18 省选模拟赛 树 倍增 LCT

    LINK:树 考虑暴力 保存每个版本的父亲 然后暴力向上跳.得分20. 考虑离线 可以离线那么就可以先把树给搞出来 然后考虑求k级祖先 可以倍增求. 如何判断合法 其实要求路径上的边的时间戳<= ...

  3. 4.17 省选模拟赛 远行 LCT 启发式合并 倍增

    容易写出nQ的暴力 由于数据是期望的时间 所以直接dfs可以跑的很快 可以拿到70分. 当然 可以进一步优化暴力 使用换根dp 然后可以将暴力优化到n^2. const int MAXN=300010 ...

  4. 4.18 省选模拟赛 无聊的计算器 CRT EXBSGS EXLucas

    算是一道很毒瘤的题目 考试的时候码+调了3h才搞定. op==1 显然是快速幂. op==2 有些点可以使用BSGS 不过后面的点是EXBSGS. 这个以前学过了 考试的时候还是懵逼.(当时还是看着花 ...

  5. 5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集

    LINK:波波老师 LINK:同bzoj 1396 识别子串 不过前者要求线性做法 后者可以log过.实际上前者也被我一个log给水过了. 其实不算很水 我自认跑的很快罢了. 都是求经过一个位置的最短 ...

  6. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  7. 18/9/21模拟赛-Updated

    18/9/21模拟赛 期望得分:100:实际得分:0  qwq 拿到题目第一眼,我去,这不是洛谷原题(仓鼠找Sugar)吗 又多看了几眼,嗯,对,除了是有多组数据外,就是原题 然后码码码....自以为 ...

  8. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  9. 5.19 省选模拟赛 小B的图 最小生成树 LCT

    LINK:小B的图 这道题就比较容易了. 容易想到将询问离线 然后 从小到大排序 那么显然是优先放正图(x+k)的边. 考虑随着x的增大 那么负图上的边会逐渐加进来 一条边被加进来当且仅当 其权值小于 ...

随机推荐

  1. CSS position 属性_css中常用position定位属性介绍

    css可以通过为元素设置一个position属性值,从而达到将不同的元素显示在不同的位置, position定位是指定位置的定位,以下为常用的几种: 1.static(静态定位): 这个是元素的默认定 ...

  2. tidyverse|数据分析常规操作-分组汇总(sumamrise+group_by)

    | 本文首发于 “生信补给站” https://mp.weixin.qq.com/s/tQt0ezYJj3H7x3aWZmKVEQ 使用tidyverse进行简单的数据处理: 盘一盘Tidyverse ...

  3. 记录一下安装hexo的过程

    记录一下安装hexo的过程 首先你的电脑需要安装node.js和Git 安装好Git之后需要配置本机与Github之间的ssh方便更新同步博客到Github上,在一个地方新建一个文件夹作为我们博客的根 ...

  4. js 整理 前端知识点 前端面试题 (2020)(vue)

    数据类型 字符串(String).数字(Number).布尔(Boolean).对空(Null).未定义(Undefined).Symbol. 引用数据类型:对象(Object).数组(Array). ...

  5. vs2019使用github

    本人操作系统win10 第一步,下载vs github插件 直接看图 下载完成后,需要关闭所有vs2019窗口,之后会弹出下面的窗口,点击modify,完成之后,重新打开vs就安装好了 下面就可以在v ...

  6. Linux系统中到底应该怎么理解系统的平均负载

    02 | 基础篇:到底应该怎么理解“平均负载”? 每次发现系统变慢时,我们通常做的第一件事,就是执行 top 或者 uptime 命令,来了解系统的负载情况.比如像下面这样,我在命令行里输入了 upt ...

  7. 机器学习实战基础(十三):sklearn中的数据预处理和特征工程(六)特征选择 feature_selection 简介

    当数据预处理完成后,我们就要开始进行特征工程了. 在做特征选择之前,有三件非常重要的事:跟数据提供者开会!跟数据提供者开会!跟数据提供者开会!一定要抓住给你提供数据的人,尤其是理解业务和数据含义的人, ...

  8. Vue小功能-视频播放之video.js

        最近在练手一个小项目,想给首页增加一个视频介绍(如下图).涉及到了vue视频播放的功能,所以在网上了解了一下.     相关的插件是Video.js,官网讲解比较详细,我罗列出来,可以根据自己 ...

  9. easyui的组合网格:combogrid的选中事件

    jQuery EasyUI的API文档中写到: “数据表格下拉框事件完全扩展自combo(自定义下拉框)和datagrid(数据表格)” 这也就是说,我们完全可以将combo和datagrid的事件拿 ...

  10. java面试题NIO与OIO的区别

    面向流与面向缓冲 Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的. Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方 ...