【loj2133】【NOI2015】品酒大会
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】品酒大会的更多相关文章
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- 洛谷 P2178 [NOI2015]品酒大会 解题报告
P2178 [NOI2015]品酒大会 题目描述 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发"首席品酒家"和 ...
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
[BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- BZOJ_4199_[Noi2015]品酒大会_后缀自动机
BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...
- [NOI2015]品酒大会(SA数组)
[NOI2015]品酒大会 题目描述 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发"首席品酒家"和" ...
- 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈
P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...
- [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并
[NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...
- [BZOJ4199][NOI2015]品酒大会
#131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...
随机推荐
- 微信小程序和微信H5测试中易出Bug的点和注意事项
一.微信小程序 易出Bug的点: 小程序的分享转发功能 背景:小程序项目开发基本完毕也都已经测过几轮,功能上基本没有什么问题,但是上线后却被客户发现通过分享转发小程序给别人,别人无法正常打开的情况 原 ...
- Java EE JSP内置对象及表达式语言
一.JSP内置对象 JSP根据Servlet API规范提供了一些内置对象,开发者不用事先声明就可使用标准变量来访问这些对象. JSP提供了9种内置对象: (一).request 简述: JSP编程中 ...
- Vue学习计划基础笔记(一) - vue实例
最近又重新看vue的文档了,计划是别人写的,之前看过一次,没有考虑太多,只考虑看懂能用就好.看完之后写过写demo,现在是零实际项目经验的,所以这一次打算细看,算是官方文档的二次产物吧,但是不是全部直 ...
- NO--10今天带大家回忆回忆“闭包”吧!
对于‘闭包,我相信很多人都掉进过这个坑里,也相信很多人没能详细的理解这个问题,今天带大家再次走进闭包: 写这篇文章时的心情是十分忐忑的,因为对于我们今天的主角:闭包,很多小伙伴都写过关于它的文章,相信 ...
- join 中的on和where的区别
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表, 然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时使用的条 ...
- [shell] 循环判断输入值
做个记录 until [[ $flag == "yes" || $flag == "exit" ]] do read -p "请确认统一/合服前后数据 ...
- php新手需要注意的高效率编程
1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍. 当然了,这个测试方法需要在十万级以上次执行,效果才明显. 其实静态方法和非静 ...
- jsp取不到值栈的值
是否页面用的重定向? <result name="addsuccess" type="redirect"> ? 去掉type="redi ...
- SQL Server数据库复制
事务复制 事务复制是一种复制类型,对订阅服务器上应用的初始数据快照,然后当发布服务器上发生数据修改时,将捕获到个别的事务并传播到订阅服务. 事务复制的原理是先将发布服务器数据库中的初始快照发送到各订阅 ...
- 1 RabbitMQ 安装,配置
1:安装 yum install -y rabbitmq-server 2:主要程序介绍 # 管理插件的程序 /usr/sbin/rabbitmq-plugins # 服务程序 /usr/sbin ...