【[NOI2015]品酒大会】

时间:2022-06-04 02:44:44

可能是最傻的做法了

暴力单调栈+\(st\)表

首先看到这道题就基本知道这是个\(SA\)了,先无脑敲上\(SA\)和求\(height\)的板子

之后尝试搞一下第一问

发现第一问就是求出满足\(lcp(i,j)>=k\)的\((i,j)\)有多少对

我们可以用一个暴力合并的单调栈来做

现在的问题转化为求出\(height\)数组所有子区间的最小值的和

我们可以考虑一个动态往序列末尾加数的过程

也就是我们往末尾加一个数都会和之前所有的数形成一个新的区间

考虑快速算出这些区间的最小值的和

我们可以对每一个数存储一个\(a_i\),表示\(i\)到当前序列末尾的最小值是多少

我们每次加入一个数可以对更新一下所有的\(a_i\),把所有比当前加入的数大的\(a_i\)变成当前数就好了

这不就\(T\)了吗

我们发现我们只需要求出所有\(a_i\)的和,并不需要关心这个\(i\)来自哪里,于是我们可以把相等的\(a_i\)放在一起计算,也就是每次新加入一个数就暴力扫一遍把那些比当前加入数大的合并到一个\(a_i\)

看起来复杂度并不科学,但是最坏情况下就相当于是一个线段树的复杂度了,\(O(n)\)的,跑的还挺快的

同时还需要维护一个时间戳,在被合并的时候利用时间戳统计一下这个元素的贡献

之后第二问,我们可以直接强上单调栈

左右两边都先用单调栈扫一遍,扫出每个点往左往右能最远达到哪里,之后我们用一个\(st\)表维护区间的最大值和最小值,每次只需要从这个点左边的区间和右边的区间里选出最大值和最小值来组合就行了

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define re register
#define LL long long
#define maxn 300005
inline LL read()
{
re char c=getchar();re LL x=0,r=1;
while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return r*x;
}
int n,m,top;
int a[maxn],cnt[maxn],T[maxn],L[maxn],R[maxn];
char S[maxn];
int tp[maxn],tax[maxn],sa[maxn],rk[maxn],het[maxn],log_2[maxn],st[maxn];
LL pre[maxn],Ans[maxn];
LL St[2][maxn][20];
inline void qsort()
{
for(re int i=0;i<=m;i++) tax[i]=0;
for(re int i=1;i<=n;i++) tax[rk[i]]++;
for(re int i=1;i<=m;i++) tax[i]+=tax[i-1];
for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
}
inline LL max(LL a,LL b){return (a>b)?a:b;}
inline LL min(LL a,LL b){return (a<b)?a:b;}
inline LL ask(int o,int l,int r)
{
int k=log_2[r-l+1];
if(o) return max(St[1][l][k],St[1][r-(1<<k)+1][k]);
else return min(St[0][l][k],St[0][r-(1<<k)+1][k]);
}
int main()
{
n=read();scanf("%s",S+1);
memset(St[0],0x3f3f3f3f,sizeof(St[0]));
memset(St[1],-0x3f3f3f3f,sizeof(St[1]));
memset(Ans,-0x3f3f3f3f,sizeof(Ans));
m=750;
for(re int i=1;i<=n;i++) rk[i]=S[i],tp[i]=i;
qsort();
for(re int w=1,p=0;p<n;m=p,w<<=1)
{
p=0;
for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
qsort();
for(re int i=1;i<=n;i++) std::swap(rk[i],tp[i]);
rk[sa[1]]=p=1;
for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
}
int k=0;
for(re int i=1;i<=n;i++)
{
if(k) --k;
int j=sa[rk[i]-1];
while(S[i+k]==S[j+k]) ++k;
het[rk[i]]=k;
}
for(re int i=2;i<=n;i++)
{
int now=1;
while(top&&a[top]>=het[i])
now+=cnt[top],pre[a[top]]+=(LL)((LL)i-(LL)T[top])*(LL)cnt[top],top--;
a[++top]=het[i],T[top]=i,cnt[top]=now;
}
while(top) pre[a[top]]+=(LL)((LL)n+1ll-(LL)T[top])*(LL)cnt[top],top--;
for(re int i=n-1;i>=0;--i) pre[i]+=pre[i+1]; for(re int i=1;i<=n;i++)
{
while(top&&het[i]<het[st[top]]) R[st[top]]=i,top--;
st[++top]=i;
}
while(top) R[st[top]]=n+1,top--;
for(re int i=n;i;--i)
{
while(top&&het[i]<het[st[top]]) L[st[top]]=i,top--;
st[++top]=i;
}
while(top) L[st[top]]=1,top--; for(re int i=1;i<=n;i++) St[0][rk[i]][0]=St[1][rk[i]][0]=read();
for(re int i=2;i<=n;i++) log_2[i]=1+log_2[i>>1];
for(re int j=1;j<=19;j++)
for(re int i=1;i+(1<<j)-1<=n;i++)
St[0][i][j]=min(St[0][i][j-1],St[0][i+(1<<(j-1))][j-1]),
St[1][i][j]=max(St[1][i][j-1],St[1][i+(1<<(j-1))][j-1]); for(re int i=1;i<=n;i++)
{
int l=L[i],r=R[i]-1;
if(l>i-1) continue;
if(i>r) continue;
LL A=ask(1,l,i-1),B=ask(0,l,i-1),C=ask(1,i,r),D=ask(0,i,r);
if(Ans[het[i]]<A*C) Ans[het[i]]=A*C; if(Ans[het[i]]<B*D) Ans[het[i]]=B*D;
if(Ans[het[i]]<A*D) Ans[het[i]]=A*D; if(Ans[het[i]]<B*C) Ans[het[i]]=B*C;
}
for(re int i=n-1;i>=0;--i) Ans[i]=max(Ans[i],Ans[i+1]);
for(re int i=0;i<n;i++)
if(pre[i]) printf("%lld %lld\n",pre[i],Ans[i]);
else printf("%lld ",pre[i]),putchar(48),putchar(10);
return 0;
}

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

  1. BZOJ 4199&colon; &lbrack;Noi2015&rsqb;品酒大会 &lbrack;后缀数组 带权并查集&rsqb;

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

  2. &lbrack;UOJ&num;131&rsqb;&lbrack;BZOJ4199&rsqb;&lbrack;NOI2015&rsqb;品酒大会 后缀数组 &plus; 并查集

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

  3. 洛谷 P2178 &lbrack;NOI2015&rsqb;品酒大会 解题报告

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

  4. 【BZOJ4199】&lbrack;Noi2015&rsqb;品酒大会 后缀数组&plus;并查集

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

  5. &lbrack;UOJ&num;131&rsqb;&lbrack;BZOJ4199&rsqb;&lbrack;NOI2015&rsqb;品酒大会

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

  6. BZOJ&lowbar;4199&lowbar;&lbrack;Noi2015&rsqb;品酒大会&lowbar;后缀自动机

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

  7. &lbrack;NOI2015&rsqb;品酒大会&lpar;SA数组&rpar;

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

  8. 洛谷P2178 &lbrack;NOI2015&rsqb;品酒大会 后缀数组+单调栈

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

  9. &lbrack;NOI2015&rsqb; 品酒大会 - 后缀数组&comma;并查集&comma;STL&comma;启发式合并

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

  10. &lbrack;BZOJ4199&rsqb;&lbrack;NOI2015&rsqb;品酒大会

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

随机推荐

  1. 学习angular&period;js的一些笔记想法&lpar;上&rpar;

    1.data-ng-app与ng-app的区别 data-ng-app是为了h5不报错 2.ng-class 不多说就来拿例子说吧 html代码 <div class='color-change ...

  2. nginx相关

    定时切割nginx日志#!/bin/bash #desc: cut nginx log #this script run at 00:00 LOG_PATH='/usr/local/nginx/log ...

  3. 手机WebAPP设计注意事项和解决方法

    1. 基本手机网页设计 1.1 wap端的网站表头 wap端的网站,写的时候首先注意表头,因为是手机端的,所以和我们平常用的web端页面的不一样,表头为: 1.2 尽量少使用水平滚动. 水平滚动除了比 ...

  4. &rsqb;Java 5&vert;6 并发包介绍

    ava.util.concurrent 包含许多线程安全.测试良好.高性能的并发构建块.不客气地说,创建 java.util.concurrent 的目的就是要实现 Collection 框架对数据结 ...

  5. JAVA写接口傻瓜(?)教程(一)

    当一个安卓开发人员/微信小程序开发者想做点什么的时候,如果他发现没有合适的接口,那么单机安卓.本地数据库emmm.没了接口就好像老人没了拐杖.盲人没了墨镜,完全可以称得上是举步维艰.生活艰难到需要自己 ...

  6. 1226 快速幂 取余运算 洛谷luogu

    还记得 前段时间学习二进制快速幂有多崩溃 当然这次方法略有不同 居然轻轻松松的 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整 ...

  7. 【Little Demo】左右按钮tab选项卡双切换

    通过前一篇文章 从简单的Tab标签到Tab图片切换 的说明,相关效果也就可以实现了. 1.左右按钮tab选项卡双切换 很明显,左右两个按钮是 absolute 布局,另外就是内容部分和Tab标签部分. ...

  8. 【Java多线程】线程同步方法概览

    一:使用syncrhoized内置锁实现同步 使用互斥来实现线程间的同步,保证共享数据在同一时刻只被一个线程使用.Java中最基本的互斥手段就是syncrhoized关键字. syncrhoized的 ...

  9. NFS生产场景优化

    1.硬件上多块网卡bond,增加吞吐量,至少千兆.sas/ssd磁盘组raid5或raid10 2.服务端配置:/data 172.16.1.0/24(rw,sync,all_squash,anonu ...

  10. JS原型与原型链图解