[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. 牛客网剑指offer第13题——调整数组顺序使得奇数位于偶数前面

    题目来源:剑指offer 题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变 ...

  2. sqlserver数据库重启

    停止:net stop mssqlserver 重启:net start mssqlserver

  3. Avro介绍

    Avro介绍   Apache Avro是一个数据序列化系统. Avro所提供的属性: 1.丰富的数据结构2.使用快速的压缩二进制数据格式3.提供容器文件用于持久化数据4.远程过程调用RPC5.简单的 ...

  4. adb -- cannot connect to x.x.x.x:5555“由于目标计算机积极拒绝,无法连接”

    原因 安卓系统未打开adb网络调试功能 通过USB方式连接到安卓系统设置即可 解决 先通过USB线连接 adb devices 能看到所连接的设备情况下 adb root 权限提权 adb shell ...

  5. 婴儿潮一代\千禧一代\X一代\Z一代含义

    (一)婴儿潮一代 婴儿潮一代是指各国的生育高峰期.每个时期的婴儿潮一代都会给各国经济带来不小的刺激作用,但同样的当他们退休时也会给政府的养老保险带来巨大的压力. 在中国,从统计数据来看生育高峰出现在1 ...

  6. .net mvc 使用 aspose.cells导出数据

    public class AsposeCellsHelper { public Workbook workBook; public Worksheet worksheet; Style style; ...

  7. Spring BeanDefinitionHolder源码解析

    BeanDefinitionHolder源码解析 继承关系 实现的接口 和BeanDefinition一样实现了BeanMetadataElement接口,获得了获取数据源(配置类的class对象)的 ...

  8. vnode

    获取vnode对象 vm.$slots对象下的所有值 vm.$scopedSlots对象的值返回一个函数,该函数执行后返回vnode对象 directives自定义指令中钩子函数的参数3和参数4,例如 ...

  9. 2020牛客寒假算法基础集训营4-F树上博弈

    链接:https://ac.nowcoder.com/acm/contest/3005/F来源:牛客网 题目描述 现有一个 n 个点,n-1条边组成的树,其中 1 号点为根节点. 牛牛和牛妹在树上玩游 ...

  10. Python标准库之hashlib模块与hmac模块

    hashlib模块用于加密相关的操作.在Python 3.x里代替了md5模块和sha模块,主要提供 SHA1.SHA224.SHA256.SHA384.SHA512 .MD5 算法.如果包含中文字符 ...