Time:2016.05.23
Author:xiaoyimi
转载注明出处谢谢


传送门
题面及样例
思路:
求lcp相关问题上有类似于差异的地方,但不完全是,”差异“所求的是lcp长度总和,而这里要对每个长度的lcp统计出现次数,更加精细
以前单调栈的做法不能满足我们了,只能另辟蹊径
(一开始我想的是线段树啥的……)
考虑这样一种思路,一开始每个后缀都是一个独立的集合,对于每个height[i],它可以把两个后缀集合x,y合并,那么对ans[height[i]]的贡献是siz[x]*siz[y],可以对最大乘积的贡献是max(这两个集合最大值的乘积,最小值的乘积)
用并查集维护每个集合的左端点,右端点,最小值和最大值
之后的事情就比较容易了
注意:
对于0相似的情况,个数肯定是n*(n-1)/2,最大值肯定是max(次大值最大值,最小值次小值)
代码:

#include<bits/stdc++.h>
#define M 300004
#define LL long long
using namespace std;
int len;
char s[M];
int minn[M],maxn[M],a[M],w[M],fa[M],sa[M],rank[M],cnt[M],tmp[M],id[M],L[M],R[M];
LL ans[2][M];
struct node
{int data,id;bool operator <(const node other)const{return data>other.data;}
}height[M];
int in()
{char ch=getchar();int t=0;bool f=0; while (!isdigit(ch)) f=(ch=='-'),ch=getchar();while (isdigit(ch)) t=(t<<1)+(t<<3)+ch-48,ch=getchar();return f?-t:t;
}
void SA(int len,int up)
{int *rk=rank,*t=tmp,d=1,p=0;for (int i=0;i<len;i++) cnt[rk[i]=w[i]]++;for (int i=1;i<up;i++) cnt[i]+=cnt[i-1];for (int i=len-1;i>=0;i--) sa[--cnt[rk[i]]]=i;for (;;){for (int i=len-d;i<len;i++) id[p++]=i;for (int i=0;i<len;i++)if (sa[i]>=d) id[p++]=sa[i]-d;for (int i=0;i<up;i++) cnt[i]=0;for (int i=0;i<len;i++) cnt[t[i]=rk[id[i]]]++;for (int i=1;i<up;i++) cnt[i]+=cnt[i-1];for (int i=len-1;i>=0;i--) sa[--cnt[t[i]]]=id[i];swap(t,rk);p=1;rk[sa[0]]=0;for (int i=0;i<len-1;i++)if (sa[i]+d<len&&sa[i+1]+d<len&&t[sa[i]]==t[sa[i+1]]&&t[sa[i]+d]==t[sa[i+1]+d])rk[sa[i+1]]=p-1;elserk[sa[i+1]]=p++;if (p==len) break;d<<=1;up=p;p=0;}
}
void Height(int len)
{for (int i=1;i<=len;i++) rank[sa[i]]=i;int k=0,x;for (int i=0;i<len;i++){k=max(k-1,0);x=sa[rank[i]-1];while (w[i+k]==w[x+k]) k++;height[rank[i]]=(node){k,rank[i]};}
}
int find(int x){return fa[x]=(x!=fa[x]?find(fa[x]):fa[x]);}
main()
{len=in();scanf("%s",s);memset(ans[1],-127,sizeof(ans[1]));for (int i=0;i<len;i++) a[i]=in();for (int i=0;i<len;i++) w[i]=s[i]-'a'+1;SA(len+1,28);Height(len);sort(height+1,height+len+1);for (int i=1;i<=len;i++) fa[i]=i,L[i]=i,R[i]=i,minn[i]=maxn[i]=a[sa[i]];for (int i=1;i<=len;i++)if (!height[i].data) break;else{int p=find(height[i].id),q=find(height[i].id-1);ans[0][height[i].data]+=(LL)(R[p]-L[p]+1)*(R[q]-L[q]+1);ans[1][height[i].data]=max((LL)minn[p]*minn[q],max(ans[1][height[i].data],(LL)maxn[p]*maxn[q]));fa[p]=q;L[q]=min(L[p],L[q]);R[q]=max(R[p],R[q]);minn[q]=min(minn[p],minn[q]); maxn[q]=max(maxn[p],maxn[q]);}for (int i=len-1;i>=1;i--)ans[0][i]+=ans[0][i+1],ans[1][i]=max(ans[1][i],ans[1][i+1]);sort(a,a+len);printf("%lld %lld\n",(LL)len*(len-1)>>1,max((LL)a[1]*a[0],(LL)a[len-2]*a[len-1]));for (int i=1;i<len;i++)printf("%lld %lld\n",ans[0][i],!ans[0][i]?0:ans[1][i]);
}

【BZOJ4199】品酒大会,后缀数组+并查集维护相关推荐

  1. [BZOJ4199][NOI2015]品酒大会-后缀数组

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

  2. P2178-[NOI2015]品酒大会【SA,并查集】

    正题 题目链接:https://www.luogu.com.cn/problem/P2178 题目大意 长度为nnn的字符串,每个位置有一个权值. 如果对于q,pq,pq,p有sq,q+r−1=sp, ...

  3. P2178 后缀数组 + 并查集

    题目传送门 题意: 调酒师  调制了  杯鸡尾酒.这  杯鸡尾酒排成一行,其中第  杯酒被贴上了一个标签  ,每杯酒有一个美味值,每个标签都是  个小写英文字母之一,把这些酒想象为一个字符串  .两个 ...

  4. 花神游历各国 题解(小清新线段树/树状数组+并查集)

    题面 众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于 ...

  5. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...

  6. F 魏迟燕的自走棋(思维+贪心+并查集维护联通块/左部点配对边<=2的匈牙利)

    https://ac.nowcoder.com/acm/contest/9984/F 参考:F 魏迟燕的自走棋(贪心+并查集) 将每个人看成一个点,武器的能力值抽象成边,这样就转化成图论的模型了. 然 ...

  7. Ural 1671 - Anansi's Cobweb 倒过来做...并查集维护..

    题意: 给出一个无向图..然后不断的删边..问每次删边后..整个图是由几个联通块组成的.... 题解: 以前做过一个题..是CF上面的...是不断的删边..并询问某两点的最短路..当时的方法是倒过来. ...

  8. NOI模拟 : Vain (并查集维护割点)

    题意: 对于 1 ≤ i ≤ n, 求出点 i 度数强制为 1 的情况下最小生成树的最大边的权值. 题解: 相当于求出删掉每个点之后的MSTMSTMST的最大值. 我们按边的权值从小到大加入新图, 很 ...

  9. 【uva12232/hdu3461】带权并查集维护异或值

    [uva12232/hdu3461]带权并查集维护异或值 题意: 对于n个数a[0]~a[n-1],但你不知道它们的值,通过逐步提供给你的信息,你的任务是根据这些信息回答问题: I P V :告诉你a ...

最新文章

  1. NOIP 2012 T2 国王游戏 (贪心+高精)
  2. HeadFirst设计模式篇十:状态模式
  3. LA 3890 (半平面交) Most Distant Point from the Sea
  4. 我的Go语言学习之旅四:各种变量的声明
  5. windows下使用nginx调试简介
  6. python银行排队系统_python-我需要基于Web的系统的消息/排队解决...
  7. js获取两个数组不同的元素并返回不同元素组成的数组,并对不同的元素添加一个新的属性
  8. vue项目PC端如何适配不同分辨率屏幕
  9. 关于“善念科技”的思考
  10. Java Socket 网络编程
  11. java options设置_JAVA_TOOL_OPTIONS和_JAVA_OPTIONS
  12. 小米路由器3 挂载U盘 实现磁盘扩展 并获取写入权限 (openwrt折腾之一)
  13. Check It Again: Progressive Visual Question Answering via Visual Entailment
  14. Python基础之Flask快速入门2
  15. Qt利用QtXlsx操作excel文件
  16. 【查找】临近省赛,Alan邀请emoji玩起了猜数字游戏活跃一下大脑。游戏规则如下:首先Alan写下几个数字让emoji猜,当emoji猜完之后,Alan会给他一个提示(java)
  17. vue内解决可视化大屏内百度地图在css transform下缩放位置偏移的问题
  18. java电子回单生成,PDF转图片
  19. 旅游可视化系统flask+pyecharts
  20. MindCV提交ISSUE规范

热门文章

  1. 还在为运维烦恼?体验云上运维服务,提意见赢好礼!【华为云分享】
  2. 自动驾驶轻松开发?华为云ModelArts赋能智慧出行
  3. 【华为云实战开发】16.DevOps交付模式下的软件测试
  4. python编程从入门到实践之外星人入侵
  5. 解析几何复习(一)向量代数
  6. 页面文字请使用css进行控制,css控制页面文字不能被选中user-select:none;
  7. 【rabbitmq安装教程】centos7下安装rabbitMQ
  8. day28 java的IO流 (1)对IO的初步了解
  9. python读取csv时keyerror_python – 读取csv文件并传输到数组的KeyError
  10. h2 不能访问localhost,SpringBoot访问H2控制台