Portal -->loj6198

Solution

​  (为什么感觉loj上面这几道后缀数组的题。。套路都是一样的啊qwq)

​  同样也是。。考虑某个区间\(height[i]\)的最小值的贡献

​​  记\(solve(i,j)\)表示统计\(rk\)值\(\in [l,r]\)的后缀对答案的贡献,那么我们有一个十分简单粗暴的想法,我们用ST表求出\([l,r]\)区间内的\(height\)最小值\(x\),记它的位置为\(mid\),如果说一开始我们先按照\(rk\)的顺序建一棵可持久化trie,那么这个时候我们就可以直接枚举\(rk\)值\(\in [l,mid-1]\)区间的后缀的\(w\),然后在\([mid,r]\)的区间内的trie上查\(w\)的最大异或值就好了

​​  但是现在的问题是,这样显然会超时

​  这里我们其实可以用一个。。类似启发式合并的思想,我们每次比较\([l,mid-1]\)和\([mid,r]\)这两个区间谁比较短,然后我们就枚举较短的区间内的\(w\)值,在另一个区间的trie上查然后更新

​  这样的复杂度我不太会证qwq但是能够过掉qwq

​​  然后可能因为我的递归写的太挫了要手动扩栈才能愉快AC菜醒qwq

​  

​  代码大概长这个样子

  1. #pragma comment(linker,"/STACK:102400000,102400000")
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #define mp make_pair
  7. #define Pr pair<int,int>
  8. #define ll long long
  9. using namespace std;
  10. const int N=1e5+10,TOP=16;
  11. char s[N];
  12. int w[N];
  13. int n;
  14. ll ans,Cnt;
  15. namespace Trie{/*{{{*/
  16. int ch[N*2*30][2],cnt[N*2*30],rt[N];
  17. int tot;
  18. int newnode(int x){
  19. ch[++tot][0]=ch[x][0]; ch[tot][1]=ch[x][1];cnt[tot]=cnt[x];
  20. return tot;
  21. }
  22. void _insert(int x,int &now,int delta,int d){
  23. now=newnode(x);
  24. ++cnt[now];
  25. if (d<0) return;
  26. int which=delta>>d&1;
  27. _insert(ch[x][which],ch[now][which],delta,d-1);
  28. }
  29. void insert(int x,int delta){_insert(!x?0:rt[x-1],rt[x],delta,TOP);}
  30. int _get_mx(int l,int r,int delta,int d){
  31. if (d<0) return 0;
  32. int which=delta>>d&1;
  33. if (cnt[ch[r][which^1]]-cnt[ch[l][which^1]])
  34. return _get_mx(ch[l][which^1],ch[r][which^1],delta,d-1)+(1<<d);
  35. return _get_mx(ch[l][which],ch[r][which],delta,d-1);
  36. }
  37. int get_mx(int l,int r,int delta){
  38. if (l==-1||r==-1) return 0;
  39. return _get_mx(rt[l-1],rt[r],delta,TOP);
  40. }
  41. }/*}}}*/
  42. namespace Sa{/*{{{*/
  43. int a[N],b[N],c[N],sa[N],height[N],rk[N];
  44. int mn[N][TOP+1],loc[N][TOP+1];
  45. int mx;
  46. bool cmp(int x,int y,int len,int *r)
  47. {return r[x]==r[y]&&r[x+len]==r[y+len];}
  48. void sort(int n){
  49. for (int i=0;i<=mx;++i) c[i]=0;
  50. for (int i=1;i<=n;++i) ++c[a[b[i]]];
  51. for (int i=1;i<=mx;++i) c[i]+=c[i-1];
  52. for (int i=n;i>=1;--i) sa[c[a[b[i]]]--]=b[i];
  53. }
  54. void get_sa(int n){
  55. int cnt=0; mx=0;
  56. for (int i=1;i<=n;++i) a[i]=s[i]-'a'+1,b[i]=i,mx=max(mx,a[i]);
  57. sort(n);
  58. for (int len=1;cnt<n;len<<=1){
  59. cnt=0;
  60. for (int i=n-len+1;i<=n;++i) b[++cnt]=i;
  61. for (int i=1;i<=n;++i)
  62. if (sa[i]>len)
  63. b[++cnt]=sa[i]-len;
  64. sort(n);
  65. swap(a,b);
  66. cnt=1; a[sa[1]]=1;
  67. for (int i=2;i<=n;a[sa[i++]]=cnt)
  68. if (!cmp(sa[i-1],sa[i],len,b)) ++cnt;
  69. mx=cnt;
  70. }
  71. }
  72. void rmq(){
  73. for (int i=1;i<=n;++i) mn[i][0]=height[i],loc[i][0]=i;
  74. for (int j=1;j<=TOP;++j)
  75. for (int i=n-(1<<j)+1;i>=1;--i)
  76. if (mn[i][j-1]<mn[i+(1<<j-1)][j-1])
  77. mn[i][j]=mn[i][j-1],loc[i][j]=loc[i][j-1];
  78. else
  79. mn[i][j]=mn[i+(1<<j-1)][j-1],loc[i][j]=loc[i+(1<<j-1)][j-1];
  80. }
  81. Pr get_lcp(int x,int y){//ranks
  82. if (x==y) return mp(n-sa[x]+1,x);
  83. if (x>y) swap(x,y);
  84. ++x;
  85. int len=y-x+1,lg=(int)(log(1.0*len)/log(2.0));
  86. if (mn[x][lg]<mn[y-(1<<lg)+1][lg])
  87. return mp(mn[x][lg],loc[x][lg]);
  88. else
  89. return mp(mn[y-(1<<lg)+1][lg],loc[y-(1<<lg)+1][lg]);
  90. }
  91. void get_height(int n){
  92. for (int i=1;i<=n;++i) rk[sa[i]]=i;
  93. int k=0;
  94. for (int i=1;i<=n;++i){
  95. if (k) --k;
  96. while (s[i+k]==s[sa[rk[i]-1]+k]) ++k;
  97. height[rk[i]]=k;
  98. }
  99. rmq();
  100. }
  101. void solve(int l,int r){
  102. if (l>=r) return;
  103. Pr tmp=get_lcp(l,r);
  104. int mid=tmp.second,lcp=tmp.first;
  105. if (r-mid+1<mid-1-l+1){
  106. for (int i=mid;i<=r;++i)
  107. ans=max(ans,1LL*lcp+Trie::get_mx(l,mid-1,w[sa[i]]));
  108. }
  109. else{
  110. for (int i=l;i<=mid-1;++i)
  111. ans=max(ans,1LL*lcp+Trie::get_mx(mid,r,w[sa[i]]));
  112. }
  113. solve(l,mid-1);
  114. solve(mid,r);
  115. }
  116. }/*}}}*/
  117. int main(){
  118. #ifndef ONLINE_JUDGE
  119. freopen("a.in","r",stdin);
  120. #endif
  121. scanf("%d",&n);
  122. scanf("%s",s+1);
  123. for (int i=1;i<=n;++i) scanf("%d",w+i);
  124. Sa::get_sa(n);
  125. Sa::get_height(n);
  126. //for (int i=1;i<=n;++i) printf("%d ",Sa::sa[i]); printf("\n");
  127. for (int i=1;i<=n;++i)
  128. Trie::insert(i,w[Sa::sa[i]]);
  129. ans=0;
  130. Sa::solve(1,n);
  131. printf("%lld\n",ans);
  132. }

【loj6198】谢特的更多相关文章

  1. [LOJ6198]谢特

    loj description 给你一个字符串和一个数组\(w_i\),定义\(\mbox{LCP}(i,j)\)为\(i,j\)两个后缀的最长公共前缀.求\(\max_{i,j}\mbox{LCP} ...

  2. loj6198谢特 后缀数组+并查集+Trie

    先把问题放在后缀数组上考虑 已知两个数组a b,求min(a[i],...,a[j])+(b[i]^b[j])的最大值 套路题 初始每个点都是一个小连通块 把a按从大到小的顺序加入,计算当前加入边作为 ...

  3. 谢欣伦 - OpenDev原创教程 - 媒体开发库libMedia

    libMedia是一个免费的简单的媒体开发库,其中的接口类与函数大都以小写的x打头,来源于我的姓氏首字母(谢欣伦). 下载 OpenDev for VS2012 libMedia提供四大功能,一是视频 ...

  4. 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRadio & CxBthRadioFind

    这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRadioFind的使用如下: void CU ...

  5. 谢欣伦 - OpenDev原创教程 - 服务端套接字类CxServerSocket

    这是一个精练的服务端套接字类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxServerSocket的使用如下(以某个叫做CSo ...

  6. 谢欣伦 - OpenDev原创教程 - 蓝牙设备查找类CxBthRemoteDeviceFind

    这是一个精练的蓝牙设备查找类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxBthRemoteDeviceFind的使用如下: ...

  7. 谢欣伦 - OpenDev原创教程 - 无连接套接字类CxUdpSocket

    这是一个精练的无连接套接字类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxUdpSocket的使用如下(以某个叫做CSomeC ...

  8. 谢欣伦 - OpenDev原创教程 - 串口类CxSerial

    这是一个精练的串口类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. 串口类CxSerial的使用如下(以某个叫做CSomeClass ...

  9. 谢欣伦 - OpenDev原创教程 - 客户端套接字类CxClientSocket

    这是一个精练的客户端套接字类,类名.函数名和变量名均采用匈牙利命名法.小写的x代表我的姓氏首字母(谢欣伦),个人习惯而已,如有雷同,纯属巧合. CxClientSocket的使用如下(以某个叫做CSo ...

随机推荐

  1. 自己动手做AI:Google AIY开发工具包解析

    2018年国际消费性电子展(CES)上,最明显的一个趋势是Amazon与Google的语音技术进驻战,如AmazonAlexa进驻到Acer笔电内,Google Assist进驻到KIA汽车内,其他如 ...

  2. 小白初识 - 快速排序(QuickSort)

    我个人觉得快速排序和归并排序有相似之处,都是用到了分治的思想,将大问题拆分成若干个小问题. 不同的地方是归并排序是先把大问题拆分好了之后再排序,而快速排序则是一边拆分,一边排序. 快速排序的原理就是, ...

  3. AsciiPic Java视频转成字符画

    AsciiPic Java视频转成字符画 github下载 https://github.com/dejavudwh/AsciiPic 运行截图 //没有做GUI 比较简陋 节省时间 main里的文件 ...

  4. MongoDB开启权限认证

      MongoDB默认安装完后,如果在配置文件中没有加上auth = true,是没有用户权限认证的,这样对于一个数据库来说是相对不安全的,尤其是在外网的情况下. 接下来是配置权限的过程: //切入到 ...

  5. Java如何调用shell脚本的

    有些时候会碰到这样的场景:java的功能里面要嵌入一个功能点,这个功能是通过是shell脚本实现的.这种时候就需要Java对脚本调用的支持了. 测试环境 Ubuntu16.04 i3-6100,12G ...

  6. Oracle和MySQL在使用上的区别

    1.  Oracle是大型数据库而MySQL是中小型数据库,MySQL是开源的而Oracle的价格非常高. 2.  Oracle支持大并发,大访问量. 3.  安装所用的空间差别也是很大,MySQL安 ...

  7. 【python 3.6】笨办法取出列表中的字典的value

    #python 3.6 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'BH8ANK' x = {'RegionSet': [{' ...

  8. Ubuntu18.04重装指南

    Guide google chrome sougou 谷歌服务助手\(\rightarrow\)谷歌访问助手(谷歌应用商店)登录谷歌账号(cnyalitea@gmail.com)然后同步. \(\te ...

  9. Java中的静态变量static

    package com.wangcf; public class Test { String name="你好"; static String sex="男"; ...

  10. java沙盒

    JAVA的安全模型不同于传统的安全方法,传统的安全方法中,大多数操作系统允许应用程序充分访问系统资源,在操作系统不提供安全保护的机器里,运行环境不能被信任.为了弥补这个缺陷,安全策略经常要求在应用程序 ...