[NOI2015] 品酒大会

Description

对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值。

Solution

很容易想到并查集,将 \(i\) 从大到小处理,每到一个新的 \(i\) ,就将所有 \(h[j]=i\) 的 \(j-1\) 与 \(j\) 两个后缀所在集合合并,维护每个集合的大小以及其中最最大次大最小次小。注意判断一下边界情况。

但是我非常懒惰,所以用了 set + 启发式合并。

  1. // How many different substrings are there in the main string
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. #define int long long
  5. int n,m=256,sa[1000005],y[1000005],u[1000005],v[1000005],o[1000005];
  6. int r[1000005],h[1000005],T,val[1000005],f[300005];
  7. char str[1000005];
  8. long long ans1,ans2=-1e18;
  9. vector <int> pos[300005];
  10. multiset <int> st[300005];
  11. int mix(multiset <int> &a, multiset <int> &b)
  12. {
  13. if(a.size()>b.size())
  14. {
  15. a.insert(b.begin(),b.end());
  16. return 0;
  17. }
  18. else
  19. {
  20. b.insert(a.begin(),a.end());
  21. return 1;
  22. }
  23. }
  24. int getans2(multiset <int> &s)
  25. {
  26. if(s.size()<2) return 0;
  27. else
  28. {
  29. multiset<int>::iterator it1,it2,it3,it4;
  30. it1=s.begin();
  31. it2=it1;
  32. ++it2;
  33. it3=s.end();
  34. --it3;
  35. it4=it3;
  36. --it4;
  37. return max((*it1)*(*it2), (*it3)*(*it4));
  38. }
  39. }
  40. int find(int x)
  41. {
  42. return f[x]==x?x:f[x]=find(f[x]);
  43. }
  44. void merge(int i,int j)
  45. {
  46. if(find(i)!=find(j))
  47. {
  48. ans1+=(int)(st[find(i)].size())*(int)(st[find(j)].size());
  49. int fg=mix(st[find(i)],st[find(j)]);
  50. if(fg) f[find(i)]=find(j);
  51. else f[find(j)]=find(i);
  52. ans2=max(ans2,getans2(st[find(i)]));
  53. }
  54. }
  55. signed main()
  56. {
  57. scanf("%lld",&n);
  58. scanf("%s",str+1);
  59. for(int i=1; i<=n; i++) scanf("%lld",&val[i]);
  60. for(int i=1; i<=n; i++) u[str[i]]++;
  61. for(int i=1; i<=m; i++) u[i]+=u[i-1];
  62. for(int i=n; i>=1; i--) sa[u[str[i]]--]=i;
  63. r[sa[1]]=1;
  64. for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
  65. for(int l=1; r[sa[n]]<n; l<<=1)
  66. {
  67. memset(u,0,sizeof u);
  68. memset(v,0,sizeof v);
  69. memcpy(o,r,sizeof r);
  70. for(int i=1; i<=n; i++) u[r[i]]++, v[r[i+l]]++;
  71. for(int i=1; i<=n; i++) u[i]+=u[i-1], v[i]+=v[i-1];
  72. for(int i=n; i>=1; i--) y[v[r[i+l]]--]=i;
  73. for(int i=n; i>=1; i--) sa[u[r[y[i]]]--]=y[i];
  74. r[sa[1]]=1;
  75. for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+((o[sa[i]]!=o[sa[i-1]])||(o[sa[i]+l]!=o[sa[i-1]+l]));
  76. }
  77. {
  78. int i,j,k=0;
  79. for(int i=1; i<=n; h[r[i++]]=k)
  80. for(k?k--:0,j=sa[r[i]-1]; str[i+k]==str[j+k]; k++);
  81. }
  82. for(int i=2; i<=n; i++)
  83. {
  84. pos[h[i]].push_back(i);
  85. }
  86. for(int i=1; i<=n; i++) st[i].insert(val[sa[i]]);
  87. for(int i=1; i<=n; i++) f[i]=i;
  88. vector <int> a1,a2;
  89. for(int i=n-1; i>=0; --i)
  90. {
  91. for(int j=0; j<pos[i].size(); j++)
  92. {
  93. merge(pos[i][j],pos[i][j]-1);
  94. }
  95. a1.push_back(ans1);
  96. a2.push_back(ans2);
  97. }
  98. for(int i=n-1; i>=0; --i) printf("%lld %lld\n",a1[i],(a2[i]<-9e17?0:a2[i]));
  99. }

[NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并的更多相关文章

  1. [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  2. 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集

    [BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...

  3. BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

    求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...

  4. 【学术篇】NOI2015 品酒大会 后缀数组+并查集

    省选前大致是刷不了几道题了... 所以就找一些裸一点的题目练练板子算了= = 然而这题一点都不裸, 也并不怎么好写... 于是就浪费了将近一下午的时间... 然而还不是因为后缀数组板子不熟= = 首先 ...

  5. NOI 2015 品酒大会 (后缀数组+并查集)

    题目大意:略 40分暴力还是很好写的,差分再跑个后缀和 和 后缀最大值就行了 一种正解是后缀数组+并查集 但据说还有后缀数组+单调栈的高端操作蒟蒻的我当然不会 后缀数组求出height,然后从大到小排 ...

  6. Uoj #131. 【NOI2015】品酒大会 后缀数组,并查集

    #131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...

  7. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  8. 【BZOJ-4199】品酒大会 后缀数组 + 并查集合并集合

    4199: [Noi2015]品酒大会 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 436  Solved: 243[Submit][Status] ...

  9. Luogu2178 NOI2015 品酒大会 SA、并查集

    传送门 感觉题目讲的很不清楚-- 题目意思就是给出一个长度为\(n\)的字符串,求对于\(r=0,1,...,n-1\),求出\(LCP(suffix_p,suffix_q) \geq r\)的无序数 ...

随机推荐

  1. jQuery---on注册事件的2种方式

    on注册事件的2种方式 on注册事件的语法 on注册简单事件 // 这个是p自己注册的事件(简单事件) $("p").on("click", function ...

  2. ROS 环境变量配置

    unbantu16.04 linux 版本,  ros系统 kinetic版本 1. ros系统可以通过rospack find  package_name  /   rosrun package_n ...

  3. Uva1213(线性筛模板+dp)

    题意: 把n拆成k个不同素数的和,有多少种拆法. 解法: 打表后dp即可,这个dp的问题可以归纳为:在n个数中选k个数,使得和m的方案数 #include<cstdio> #include ...

  4. Pikachu-Sql Inject(SQL注入)

    在owasp发布的top10排行榜里,注入漏洞一直是危害排名第一的漏洞,其中注入漏洞里面首当其冲的就是数据库注入漏洞.一个严重的SQL注入漏洞,可能会直接导致一家公司破产!SQL注入漏洞主要形成的原因 ...

  5. Spark性能优化指南——初级篇

    原文来我的公众号:Spark性能优化指南——初级篇 一. Spark作业原理 我们使用spark-submit提交一个Spark作业之后,这个作业就会启动一个对应的Driver进程.该进程是向集群管理 ...

  6. 了解SIT和UAT的基本内涵

    SIT:System Integration Test(系统集成测试,即内部测试)根据用例描述测试每一个场景,优化系统性能,提交数据库性能excution plan给DBA review.对系统进行压 ...

  7. Excel时间格合并(年月日+时间点)

    =value(a1)+b2 日期 时间 合并 2018/8/8 14:13 2018/8/8 14:13:00      

  8. 题解【AcWing1090】绿色通道

    题面 题目要求出最长的空题段最短的长度,显然可以二分答案. 考虑如何 check. 设二分到的值是 \(x\),即最长的空题段长度至少为 \(x\). 其实整个 check 的过程可以看作一个 DP, ...

  9. gitlab 备份和恢复

    前言 gitlab这个代码托管工具真是强大,很多东西都是做好了直接用的. 这里就包括备份和恢复功能. 正文 备份 我们可以直接运行此命令,来进行备份. sudo gitlab-rake gitlab: ...

  10. python数据分析学习(1)pandas一维工具Series讲解

    目录 一:pandas数据结构介绍   python是数据分析的主要工具,它包含的数据结构和数据处理工具的设计让python在数据分析领域变得十分快捷.它以NumPy为基础,并对于需要类似 for循环 ...