自己尝试敲后缀数组,发现难看(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. JNDI数据源配置

    一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下:   ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Connec ...

  2. Python: scikit-image Blob detection

    这个用例主要介绍利用三种算法对含有blob的图像进行检测,blob 或者叫斑点,就是在一幅图像上,暗背景上的亮区域,或者亮背景上的暗区域,都可以称为blob.主要利用blob与背景之间的对比度来进行检 ...

  3. POJ2155 Matrix(二维树状数组||区间修改单点查询)

    Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row an ...

  4. XML配置中 引入外部property文件

    新建properties配置文件 内容如下: jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\ ...

  5. ACM学习历程—BestCoder 2015百度之星资格赛1002 列变位法解密(vector容器)

    Problem Description 列变位法是古典密码算法中变位加密的一种方法,具体过程如下 将明文字符分割成个数固定的分组(如5个一组,5即为密钥),按一组一行的次序整齐排列,最后不足一组不放置 ...

  6. [转]JavaScript的实例化与继承:请停止使用new关键字

    JavaScript中的new关键字可以实现实例化和继承的工作,但个人认为使用new关键字并非是最佳的实践,还可以有更友好一些的实现.本文将介绍使用new关键字有什么问题,然后介绍如何对与new相关联 ...

  7. AtCoder Grand Contest 028 A:Two Abbreviations

    题目传送门:https://agc028.contest.atcoder.jp/tasks/agc028_a 题目翻译 给你两个串\(s\)与\(t\),长度分别为\(n,m\).问你存不存在一个串长 ...

  8. 创建自己的YUM仓库

    1. 首先,假定我们应用的名字叫helloworld(可以参考简单 RPM 包制作来创建两个版本helloworld安装RPM包,helloworld-1.0.0-1.el6.x86_64.rpm和h ...

  9. UVa 714 Copying books 贪心+二分 最大值最小化

    题目大意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相 ...

  10. [hdu3853]LOOPS(概率dp)

    题意:迷宫是一个R*C的布局,每个格子中给出停留在原地,往右走一个,往下走一格的概率,起点在(1,1),终点在(R,C),每走一格消耗两点能量,求出最后所需要的能量期望. 解题关键:概率dp反向求期望 ...