自己尝试敲后缀数组,发现难看(tiao)的不行,于是抄了板子

考虑建出hei以后转化出的问题:

对于一个数组中权值大于等于k的连续部分,求取两个数的方案数和两数积的最大值

(好气啊,可以有负数)

把询问倒序以后相当于连续部分之间会动态加元素,使他们连起来

维护一段极大连续段的最大值、最小值、长度,保存在左右两端——wtf我也不知道这算什么做法

然后瞎**乱搞一下,就能每次合并O(1)维护出来了(似乎没比并查集好多少)

 #include <bits/stdc++.h>
#define N 300001
#define MIN -9223372036854775807
#define calc(x) (x)*((x)-1)/2
#define ll long long
using namespace std;
ll n,ans,ans2;
ll c[N],mi[N],ma[N],len[N],w[N];
ll sa[N],Rank[N],height[N];
ll wa[N],wb[N],wv[N],wd[N];
ll out1[N],out2[N];
struct node
{
ll x,y;
node(ll p,ll q)
{
x=p;y=q;
}
node()
{
}
} t[N];
bool cmp(ll *r,ll a,ll b,ll l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
bool com(node a,node b)
{
return a.x>b.x;
}
void da(ll *r,ll n,ll m)
{
ll *x=wa,*y=wb,*t;
for (ll i=;i<m;i++) wd[i]=;
for (ll i=;i<n;i++) wd[x[i]=r[i]]++;
for (ll i=;i<m;i++) wd[i]+=wd[i-];
for (ll i=n-;i>=;i--) sa[--wd[x[i]]]=i;
for (ll j=,p=,i;p<n;j<<=,m=p)
{
for (p=,i=n-j;i<n;i++) y[p++]=i;
for (i=;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
for (i=;i<n;i++) wv[i]=x[y[i]];
for (i=;i<m;i++) wd[i]=;
for (i=;i<n;i++) wd[wv[i]]++;
for (i=;i<m;i++) wd[i]+=wd[i-];
for (i=n-;i>=;i--) sa[--wd[wv[i]]]=y[i];
for (t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
}
void get_height(ll *r,ll n)
{
for (ll i=;i<=n;i++) Rank[sa[i]]=i;
for (ll i=,k=,j;i<n;height[Rank[i++]]=k)
for (k?k--:,j=sa[Rank[i]-];r[i+k]==r[j+k];k++);
}
void merge(ll x,ll y)
{
if(!len[x] || !len[y]) return;
ans2+=calc(len[x]+len[y]+)-calc(len[x]+)-calc(len[y]+);
ans=max(ans,w[sa[x-len[x]]]*mi[y]);ans=max(ans,mi[x]*mi[y]);
ans=max(ans,w[sa[x-len[x]]]*ma[y]);ans=max(ans,ma[x]*ma[y]);
ll MI=min(mi[x],mi[y]),MA=max(ma[x],ma[y]);
mi[x-len[x]+]=mi[y+len[y]-]=MI;
ma[x-len[x]+]=ma[y+len[y]-]=MA;
len[x-len[x]+]=len[y+len[y]-]=len[x]+len[y];
}
void add(ll now)
{
if(!now) return;
len[now]=;
mi[now]=ma[now]=w[sa[now]];
ans=max(ans,w[sa[now]]*w[sa[now-]]);
++ans2;
if(now)
merge(now-,now);
if(now<n-)
merge(now,now+);
}
int main()
{
scanf("%lld",&n);
for(ll i=;i<n;i++)
{
char ch;
while(ch=getchar(),!isalpha(ch));
c[i]=ch-'a'+;
}
for(ll i=;i<n;i++)
scanf("%lld",&w[i]);
c[n]=;
da(c,n+,);
get_height(c,n);
for(ll i=;i<n;i++)
sa[i]=sa[i+],height[i]=height[i+];
if()
for(ll i=;i<n;i++)
{
printf("%lld %lld\n",sa[i],height[i]);
}
for(ll i=;i<n;i++)
t[i]=node(height[i],i);
sort(t,t+n,com);
ll j=;
ans=MIN;ans2=;
for(ll i=;i<n;i++)
len[i]=,ma[i]=MIN,mi[i]=-MIN;
for(ll i=n-;i>=;i--)
{
while(j<n && t[j].x==i) add(t[j].y),j++;
out1[i]=ans2;out2[i]=(ans==MIN)?:ans;
}
for(ll i=;i<n;i++)
printf("%lld %lld\n",out1[i],out2[i]);
return ;
}

NOI2015品酒大会 后缀数组的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

    求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...

  6. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

  7. 【学术篇】NOI2015 品酒大会 后缀数组+并查集

    省选前大致是刷不了几道题了... 所以就找一些裸一点的题目练练板子算了= = 然而这题一点都不裸, 也并不怎么好写... 于是就浪费了将近一下午的时间... 然而还不是因为后缀数组板子不熟= = 首先 ...

  8. luoguP2178 [NOI2015]品酒大会(后缀数组做法)

    题意 因为一个\(k\)相似必定为\(k-1,k-2....0\)相似,对于一个\(lcp\)为\(k\)后缀对\((i,j)\),我们只用把它的贡献加在\(k\)的答案上,最后求一个后缀和和后缀ma ...

  9. 【BZOJ-4199】品酒大会 后缀数组 + 并查集合并集合

    4199: [Noi2015]品酒大会 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 436  Solved: 243[Submit][Status] ...

随机推荐

  1. HTML5响应式导航

    HTML5响应式导航HTML5,响应式,jQuery特效,HTML5导航,HTML5响应式导航是一款基于HTML5实现的深灰色响应式导航菜单. 地址:http://www.huiyi8.com/sc/ ...

  2. hdu 4704 sum(费马小定理+快速幂)

    题意: 这题意看了很久.. s(k)表示的是把n分成k个正整数的和,有多少种分法. 例如: n=4时, s(1)=1     4 s(2)=3     1,3      3,1       2,2 s ...

  3. Linux_异常_04_ftp: command not found...

    今天在centos上使用ftp命令连接本机的FTP服务器(本机FTP服务使用Vsftpd搭建),出现如下的错误提示:-bash: ftp: command not found 查询相关资料,发现很有可 ...

  4. ACM学习历程—NPU1086 随机数 2015年陕西省程序设计竞赛网络预赛(正式赛)C题 (计数排序 || set容器)

    Description 开学了,ACM队的边老板想在学校中请一些妹子一起做一项问卷调查,调查妹子们对ACM的了解情况,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100), ...

  5. MongoDB 分片的原理、搭建、应用 !

    MongoDB 分片的原理.搭建.应用   一.概念: 分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程.将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处 ...

  6. java 获取 HttpServletRequest 值 demo

    private void getHttpServletRequestInfo(HttpServletRequest request){ try { StringBuilder stringBuilde ...

  7. mysql create table

  8. stm32之复位与待机唤醒

    一.复位 stm32复位有三种类型,分别为系统复位.电源复位和备份域复位. 其中系统复位又分为: NRST引脚低电平(外部复位) 窗口看门狗计数结束 独立看门狗计数结束 软件复位 低功耗管理复位 二. ...

  9. CF-816A

    A. Karen and Morning time limit per test 2 seconds memory limit per test 512 megabytes input standar ...

  10. 《Java多线程编程核心技术》读后感(八)

    不使用等待/通知机制实现线程间通信 使用sleep()结合while(true)死循环来实现多个线程间通信 package Third; import java.util.ArrayList; imp ...