[NOI2015] 品酒大会

Description

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

Solution

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

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

// How many different substrings are there in the main string
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m=256,sa[1000005],y[1000005],u[1000005],v[1000005],o[1000005];
int r[1000005],h[1000005],T,val[1000005],f[300005];
char str[1000005];
long long ans1,ans2=-1e18;
vector <int> pos[300005];
multiset <int> st[300005]; int mix(multiset <int> &a, multiset <int> &b)
{
if(a.size()>b.size())
{
a.insert(b.begin(),b.end());
return 0;
}
else
{
b.insert(a.begin(),a.end());
return 1;
}
} int getans2(multiset <int> &s)
{
if(s.size()<2) return 0;
else
{
multiset<int>::iterator it1,it2,it3,it4;
it1=s.begin();
it2=it1;
++it2;
it3=s.end();
--it3;
it4=it3;
--it4;
return max((*it1)*(*it2), (*it3)*(*it4));
}
} int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
void merge(int i,int j)
{
if(find(i)!=find(j))
{
ans1+=(int)(st[find(i)].size())*(int)(st[find(j)].size());
int fg=mix(st[find(i)],st[find(j)]);
if(fg) f[find(i)]=find(j);
else f[find(j)]=find(i);
ans2=max(ans2,getans2(st[find(i)]));
}
} signed main()
{
scanf("%lld",&n);
scanf("%s",str+1);
for(int i=1; i<=n; i++) scanf("%lld",&val[i]); for(int i=1; i<=n; i++) u[str[i]]++;
for(int i=1; i<=m; i++) u[i]+=u[i-1];
for(int i=n; i>=1; i--) sa[u[str[i]]--]=i;
r[sa[1]]=1;
for(int i=2; i<=n; i++) r[sa[i]]=r[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]); for(int l=1; r[sa[n]]<n; l<<=1)
{
memset(u,0,sizeof u);
memset(v,0,sizeof v);
memcpy(o,r,sizeof r);
for(int i=1; i<=n; i++) u[r[i]]++, v[r[i+l]]++;
for(int i=1; i<=n; i++) u[i]+=u[i-1], v[i]+=v[i-1];
for(int i=n; i>=1; i--) y[v[r[i+l]]--]=i;
for(int i=n; i>=1; i--) sa[u[r[y[i]]]--]=y[i];
r[sa[1]]=1;
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]));
}
{
int i,j,k=0;
for(int i=1; i<=n; h[r[i++]]=k)
for(k?k--:0,j=sa[r[i]-1]; str[i+k]==str[j+k]; k++);
} for(int i=2; i<=n; i++)
{
pos[h[i]].push_back(i);
}
for(int i=1; i<=n; i++) st[i].insert(val[sa[i]]);
for(int i=1; i<=n; i++) f[i]=i;
vector <int> a1,a2;
for(int i=n-1; i>=0; --i)
{
for(int j=0; j<pos[i].size(); j++)
{
merge(pos[i][j],pos[i][j]-1);
}
a1.push_back(ans1);
a2.push_back(ans2);
}
for(int i=n-1; i>=0; --i) printf("%lld %lld\n",a1[i],(a2[i]<-9e17?0:a2[i]));
}

[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. 使用ASP.NET Core 3.x 构建 RESTful API - 5.1 输入验证

    说到验证,那就需要做三件事: 定义验证规则 按验证规则进行检查 报告验证的错误.在把错误报告给API消费者的时候,报告里并不包含到底是服务端还是API消费者引起的错误,这是状态码的工作.而通常响应的B ...

  2. Linux中“没有可用的软件包XX,但是它被其他软件包引用”的解决方法

    踩坑经历 今天刚在虚拟机上安装好了ubuntu系统,在执行sudo apt install net-tools 命令时报错"没有可用的软件包net-tools,但是它被其他软件包引用&quo ...

  3. 《茶余饭后小故事》MV*、MVC、MVP、MVVM的前世今生

    今天我们讲讲历史,讲讲故事,不扯高深术语. MV*表示的意思是:M(Model逻辑层) + View(视图层) + *(中间者).上帝提出了这个逻辑与视图分离,用中间者进行连接的伟大思想,并将实现这个 ...

  4. 制作MySQL RPM安装包Spec

    适用环境: 数据库版本:MySQL 操作系统:CentOS 7 制作思路: 将数据库初始化和配置工作放到安装脚本中方便定制: 1.打包MySQL应用目录 2.不自动生成配置文件 3.不自动生成数据目录 ...

  5. 简单的leetcode题

    简单的leetcode题 环绕字符串中唯一的子字符串 把字符串 s 看作是\("abcdefghijklmnopqrstuvwxyz"\)的无限环绕字符串,所以 s 看起来是这样的 ...

  6. 修改sudoers

    使用visudo命令 [root@898f990a8808 etc]# visudo

  7. ubuntu set up 6 - NTFS Mount

    1. NTFS Mounted as read-only https://askubuntu.com/questions/1138076/ubuntu-18-04-cant-write-on-ntfs ...

  8. Verilog-case、casez和casex的区别

    参考博客:https://www.cnblogs.com/guolongnv/articles/6906929.html 1.基本概念 1)?表示z,而不是“dont care” 2)区分: case ...

  9. WPF 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改

    该问题出现在WPF中的VM类中,ObservableCollection类型,该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改, ...

  10. ES6实现图片切换特效

    效果图 demo.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...