Portal --> loj2133

Solution

  虽然说这题貌似用后缀树之类的好像会更加简短一点。。但是还是因为在智力康复所以就还是用后缀数组好了嗯(哇好感动啊难得那么顺畅写了一道noi的题qwq以及为什么我调试的时候调的都是树状数组的部分啊。。)

  其实仔细想一下,\(k\)相似的答案对\(x\in [0,k-1]\)相似的答案都是由贡献的,也就是说大概是一个后缀和或者后缀最大值的感觉,所以这里就产生了一个最初步的想法我们也许可以用树状数组来统计答案

​  然后接着考虑怎么算相似度最大为\(k\)的贡献

  其实这题的套路和Portal -->「HAOI2016」找相同字符几乎是。。一样的

​  同样的我们也是从\(height[i]\)作为区间最小值的贡献这个方向来考虑:我们记\(solve(l,r)\)表示处理\(rk\)值\(\in [l,r]\)的后缀对答案的贡献,然后可以用ST表预处理之后\(O(1)\)求得整一个区间内的\(height\)的最小值\(x\),也就是这整一个区间内的任意两个后缀的\(lcp\)一定满足\(lcp>=x\),即相似值一定\(>=x\)

​  统计方案数的话,我们就直接找到这个最小值的位置\(mid\),往树状数组中\(x\)的位置丢入\(((mid-1)-l+1)*(r-mid+1)\)即可(就是在\([l,mid-1]\)中选一个,在\([mid,r]\)中选一个)

  统计美味度的最大值的话,我们也是可以用ST表预处理出\(rk\)值\(\in [l,r]\)的后缀开头位置的美味度最大值和最小值,然后查询区间\([l,mid-1]\)中的最大值最小值(记为\(recl.fir\)和\(recl.sec\)),以及区间\([mid,r]\)中的最大值最小值(记为\(recr.fir\)和\(recr.sec\)),然后往记录最大值的树状数组中\(x\)的位置丢入\(max(recl.fir*recr.fir,recl.sec*recr.sec)\)即可

​  稍微说明一下需要记录最大和最小值的原因是这里的美味度可能是负数

​  然后处理完当前区间之后我们再递归处理\([l,mid-1]\)和\([mid,r]\)就好了(同样的这里的区间的开闭之类的也是可以根据个人喜好自己更改的反正。。上面查询什么的跟递归处理的一致就好了)

​  然后最后直接对于每一个不同的相似度在两个树状数组中分别\(log\)的时间查询一下就好了

​  最后有一个小细节:在ST表查询\(height\)最小值的时候,因为我们\(height\)的定义是与前一个相邻的后缀的\(lcp\),所以查询的下界需要\(+1\),而查询美味度最大值的时候并不需要,如果这两个查询放在一起写的话(比如说。。我这种写法qwq),要稍微注意一下

  

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define Pr pair<int,int>
#define mp make_pair
#define ll long long
using namespace std;
const int N=3*(1e5)+10,TOP=20;
const ll inf=(1e18)+10;
char s[N];
ll V[N],lis[N],a[N];
int n,m;
bool cmp(int x,int y){return x>y;}
struct Data{/*{{{*/
ll fir,sec;
Data(){}
Data(ll fir1,ll sec1) {fir=fir1; sec=sec1;}
friend Data update(Data x,Data y){
static ll tmp[4];
tmp[0]=x.fir; tmp[1]=x.sec; tmp[2]=y.fir; tmp[3]=y.sec;
sort(tmp,tmp+4,cmp);
x.fir=tmp[0]; x.sec=tmp[3];
return x;
}
};/*}}}*/
namespace Bit_sum{/*{{{*/
ll c[N];
int mx;
void init(int _mx){
mx=_mx;
for (int i=0;i<=mx;++i) c[i]=0;
}
void insert(int x,ll delta){
for (;x;x-=x&-x) c[x]+=delta;
}
ll query(int x){
ll ret=0;
for (;x<=mx;x+=x&-x) ret+=c[x];
return ret;
}
}/*}}}*/
namespace Bit_mx{/*{{{*/
ll c[N];
int mx;
void init(int _mx){
mx=_mx;
for (int i=0;i<=mx;++i) c[i]=-inf;
}
void insert(int x,ll delta){
for (;x;x-=x&-x) c[x]=max(c[x],delta);
}
ll query(int x){
ll ret=-inf;
for (;x<=mx;x+=x&-x) ret=max(ret,c[x]);
return ret==-inf?0:ret;
}
}/*}}}*/
namespace Sa{/*{{{*/
int a[N],b[N],c[N],sa[N],height[N],rk[N];
int mn[N][TOP+1],loc[N][TOP+1];
Data val[N][TOP+1];
int mx;
bool cmp(int x,int y,int len,int *r)
{return r[x]==r[y]&&r[x+len]==r[y+len];}
void Sort(int n){
for (int i=0;i<=mx;++i) c[i]=0;
for (int i=1;i<=n;++i) ++c[a[b[i]]];
for (int i=1;i<=mx;++i) c[i]+=c[i-1];
for (int i=n;i>=1;--i) sa[c[a[b[i]]]--]=b[i];
}
void get_sa(int n){
mx=0;
for (int i=1;i<=n;++i) a[i]=s[i]-'a'+1,b[i]=i,mx=max(mx,a[i]);
int cnt=0;
Sort(n);
for (int len=1;cnt<n;len<<=1){
cnt=0;
for (int i=n-len+1;i<=n;++i) b[++cnt]=i;
for (int i=1;i<=n;++i)
if (sa[i]>len)
b[++cnt]=sa[i]-len;
Sort(n);
swap(a,b);
cnt=1; a[sa[1]]=1;
for (int i=2;i<=n;a[sa[i++]]=cnt)
if (!cmp(sa[i],sa[i-1],len,b)) ++cnt;
mx=cnt;
}
}
void rmq(){
for (int i=1;i<=n;++i){
mn[i][0]=height[i],loc[i][0]=i;
val[i][0]=Data(V[sa[i]],V[sa[i]]);
}
for (int j=1;j<=TOP;++j)
for (int i=n-(1<<j)+1;i>=1;--i){
if (mn[i][j-1]<mn[i+(1<<j-1)][j-1]){
mn[i][j]=mn[i][j-1],loc[i][j]=loc[i][j-1];
}
else{
mn[i][j]=mn[i+(1<<j-1)][j-1],loc[i][j]=loc[i+(1<<j-1)][j-1];
}
val[i][j]=update(val[i][j-1],val[i+(1<<j-1)][j-1]);
}
}
void get_height(int n){
for (int i=1;i<=n;++i) rk[sa[i]]=i;
int k=0;
for (int i=1;i<=n;++i){
if (k) --k;
while (s[i+k]==s[sa[rk[i]-1]+k]) ++k;
height[rk[i]]=k;
}
rmq();
}
Pr get_lcp(int x,int y,Data &ret){//ranks
if (x==y){
ret=val[x][0];
return mp(n-sa[x]+1,x);
}
if (x>y) swap(x,y);
++x;
int len=y-x+1,lg=(int)(log(1.0*len)/log(2.0)),lg1=(int)(log(1.0*(len+1))/log(2.0));
ret=update(val[x-1][lg1],val[y-(1<<lg1)+1][lg1]);
if (mn[x][lg]<mn[y-(1<<lg)+1][lg])
return mp(mn[x][lg],loc[x][lg]);
else
return mp(mn[y-(1<<lg)+1][lg],loc[y-(1<<lg)+1][lg]);
}
void solve(int l,int r){
if (l>=r) return;
Data recl,recr;
Pr tmp=get_lcp(l,r,recl);
int lcp=tmp.first,mid=tmp.second;
get_lcp(l,mid-1,recl);
get_lcp(mid,r,recr); Bit_mx::insert(lcp+1,max(recl.fir*recr.fir,recl.sec*recr.sec)); Bit_sum::insert(lcp+1,1LL*(mid-1-l+1)*(r-mid+1));
solve(l,mid-1);
solve(mid,r);
}
}/*}}}*/ int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d",&n);
scanf("%s",s+1);
for (int i=1;i<=n;++i) scanf("%lld",V+i);
Sa::get_sa(n);
Sa::get_height(n);
Data ttmp;
Bit_mx::init(n); Bit_sum::init(n);
Sa::solve(1,n);
for (int i=1;i<=n;++i)
printf("%lld %lld\n",Bit_sum::query(i),Bit_mx::query(i));
}

【loj2133】【NOI2015】品酒大会的更多相关文章

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

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

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

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

  3. 洛谷 P2178 [NOI2015]品酒大会 解题报告

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

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

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

  5. [UOJ#131][BZOJ4199][NOI2015]品酒大会

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

  6. BZOJ_4199_[Noi2015]品酒大会_后缀自动机

    BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...

  7. [NOI2015]品酒大会(SA数组)

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

  8. 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈

    P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...

  9. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

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

  10. [BZOJ4199][NOI2015]品酒大会

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

随机推荐

  1. oss上传文件0字节

    最近使用oss上传文件,不同项目中使用的版本也不同,之前的都能正常上传,最近因需要添加ObjectMetaData属性,扩展了一个方法,发现上传的文件始终是0字节的,最终跟源码发现conntentLe ...

  2. Python中abs()和math.fabs()区别

    描述:Python中fabs(x)方法返回x的绝对值.虽然类似于abs()函数,但是两个函数之间存在以下差异: abs()是一个内置函数,而fabs()在math模块中定义的. fabs()函数只适用 ...

  3. RabbitMQ各协议异同详解

    一.官网介绍 Which protocols does RabbitMQ support? RabbitMQ supports several messaging protocols, directl ...

  4. LearnPython - Zip格式文件的解压缩

    import zipfile import os def unzip(zip_name, target_dir): files = zipfile.ZipFile(zip_name) for zip_ ...

  5. 基于Docker Compose构建的MySQL MHA集群

    Docker MySQL MHA 基于Docker 1.13.1之上构建的MySQL MHA Docker Compose Project 可快速启动GTID模式下的MasterHA集群, 主用于My ...

  6. Scrum立会报告+燃尽图(十月十七日总第八次):分配Alpha阶段任务

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...

  7. 关《我是IT小小鸟》有感

    我一直认为大学就是一个自由的舒适的学习环境,没有人可以干扰你限制你,以至于我到了大学之后只剩下了颓废的生活.每天上课玩手机,下课玩电脑,吃饭叫外卖,从不去锻炼,周末就熬夜通宵,状态越来越差,导致我逐渐 ...

  8. mvc4 找到多个与名为“xx”的控制器匹配的类型

    asp.net mvc4 添加分区出现错误 找到多个与名为“home”的控制器匹配的类型 会出现如下错误”找到多个与名为“home”的控制器匹配的类型“ 在RouteConfig文件中添加命名空间可解 ...

  9. JavaWeb应用的生命周期

    JavaWeb应用的生命周期是由Servlet容器来控制. 启动阶段 (1)读取web.xml配置文件数据 (2)为JavaWeb应用创建一个ServletContext对象 (3)对所有的Filte ...

  10. QJsonDocument实现Qt下JSON文档读写

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QJsonDocument实现Qt下JSON文档读写     本文地址:http://tech ...