【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]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...
随机推荐
- Web自动化常用方法封装(不定时更新)
/** * JScript实现鼠标悬停 */public void mouseHoverJScript(By by,WebElement HoverElement) { // TODO Auto-ge ...
- Linux文件归档和解压缩
1.tar tar命令相当于归档,不做压缩,解压同样也是把归档文件释放出来(归档通俗上可以理解为把文件分类,把一些文件放到一个包中归类,方便用户管理) 解包:tar -zxvf file.tar #解 ...
- lxd&openstack-lxd源码剖析
lxd:https://linuxcontainers.org/lxd/,目标是融入到openstack体系被管理,像虚拟机一样被管理使用.从如下图可知,并非走的是libvirt-lxc路线,而是no ...
- BVT、EVT、DVT、PVT产品开发几个阶段
EVT EVT(Engineering Verification Test) 工程验证 产品开发初期的设计验证.设计者实现样品时做初期的测试验证,包括 功能和安规测试,一般由 RD(Researc ...
- 字符串拆分和拼接(含list拼接)---基于python
最近得一超长字符串如下: l=“5245474953544552207369703a3137322e3136312e31302e323232205349502f322e300d0a5669613a20 ...
- python 抓取网页(一)
#-------PYTHON获取网页内容-------------# import sys, urllib url = "http://www.baidu.com" #网页地址 w ...
- PSP Daily——团队项目Alpha发布
视频展示:优酷视频链接.文案如下 PSP Daily软件NABCD分析: 1) N (Need 需求) PSP Daily 解决了用户(软件工程课上学生)记录例行报告.写每周PSP表格和统计的需求.潜 ...
- Requests库与HTTP协议
了解HTTP协议 请求与响应模式的协议: 用户提出对URL(用来定位网络中的资源位置)地址数据的操作请求,服务器给予相应. 无状态的应用层协议:两次请求之间不会互相影响. HTTP协议支持的请求种类: ...
- Xcode 6添加模板无效
最近发现从Xcode 5拷贝来的模板在Xcode 6上是OK的,但是自己自定义的却不行,一直使用的是自定义的基类模板,最后发现原因是没有在 TemplateInfo.plist 中注册自定义的模板,注 ...
- android入门 — 多线程(一)
android中的一些耗时操作,例如网络请求,如果不能及时响应,就会导致主线程被阻塞,出现ANR,非常影响用户体验,所以一些耗时的操作,我们会想办法放在子线程中去完成. android的UI操作并不是 ...