【NOI2015】【BZOJ4199】品酒大会
2015-08-26 10:37
435 查看
Description
Input
Output
Sample Input
Sample Output
HINT
Source
BZOJ无题面233
反正网上一堆自己下载叭>_<
对反串建SAM然后DP
第一问和AHOI2013差异完全一样
具体解法:
设Ans1[i]为lcp恰为i的后缀对数,Ans2[i]为lcp恰为i的后缀的价值乘积的最大值
建出SAM后,记录子树中后缀个数、价值的最大值、价值的最小值,然后O(n)DP即可
在SAM里DP完记得最后统计到Ans1和Ans2里去
size会爆int…一开始开的int一直WAWAWAWA…
Input
Output
Sample Input
Sample Output
HINT
Source
BZOJ无题面233
反正网上一堆自己下载叭>_<
对反串建SAM然后DP
第一问和AHOI2013差异完全一样
具体解法:
设Ans1[i]为lcp恰为i的后缀对数,Ans2[i]为lcp恰为i的后缀的价值乘积的最大值
建出SAM后,记录子树中后缀个数、价值的最大值、价值的最小值,然后O(n)DP即可
在SAM里DP完记得最后统计到Ans1和Ans2里去
size会爆int…一开始开的int一直WAWAWAWA…
[code]#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MAXN 600100 #define LL long long #define MAXINT 1ll<<60 using namespace std; int n,top; LL A[MAXN]; char ch[MAXN]; LL Ans1[MAXN],Ans2[MAXN]; struct edge { int to; edge *next; }e[MAXN<<1],*prev[MAXN]; void insert(int u,int v) { e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top]; } void in(LL &x) { char ch=getchar();x=0;int flag=1; while (!(ch>='0'&&ch<='9')) flag=ch=='-'?-1:1,ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();x*=flag; } struct sam { int cnt,last,p,q,np,nq; int a[MAXN][26],len[MAXN],fa[MAXN]; LL maxn[MAXN],minn[MAXN],ans1[MAXN],ans2[MAXN],size[MAXN]; sam() { last=++cnt; } void insert(int c,int x) { p=last;last=np=++cnt;len[np]=len[p]+1;size[np]=1;maxn[np]=minn[np]=A[x]; while (!a[p][c]&&p) a[p][c]=np,p=fa[p]; if (!p) fa[np]=1; else { q=a[p][c]; if (len[q]==len[p]+1) fa[np]=q; else { nq=++cnt;len[nq]=len[p]+1;maxn[cnt]=-MAXINT;minn[cnt]=MAXINT; memcpy(a[nq],a[q],sizeof(a[q])); fa[nq]=fa[q];fa[q]=fa[np]=nq; while (a[p][c]==q) a[p][c]=nq,p=fa[p]; } } } }sam; void dfs(int x) { for (edge *i=prev[x];i;i=i->next) { dfs(i->to); sam.ans1[x]+=sam.size[x]*sam.size[i->to]; sam.size[x]+=sam.size[i->to]; if (sam.maxn[x]!=-MAXINT) sam.ans2[x]=max(sam.ans2[x],sam.maxn[i->to]*sam.maxn[x]); if (sam.minn[x]!=MAXINT) sam.ans2[x]=max(sam.ans2[x],sam.minn[i->to]*sam.minn[x]); sam.maxn[x]=max(sam.maxn[x],sam.maxn[i->to]); sam.minn[x]=min(sam.minn[x],sam.minn[i->to]); } } int main() { freopen("savour.in","r",stdin); freopen("savour.out","w",stdout); scanf("%d",&n); scanf("%s",ch);sam.maxn[1]=-MAXINT;sam.minn[1]=MAXINT; for (int i=1;i<=n;i++) in(A[i]); for (int i=n;i;i--) sam.insert(ch[i-1]-'a',i); for (int i=0;i<=sam.cnt;i++) sam.ans2[i]=-MAXINT; for (int i=1;i<=sam.cnt;i++) insert(sam.fa[i],i); dfs(1); for (int i=0;i<n;i++) Ans2[i]=-MAXINT; for (int i=1;i<=sam.cnt;i++) Ans1[sam.len[i]]+=sam.ans1[i],Ans2[sam.len[i]]=max(Ans2[sam.len[i]],sam.ans2[i]); for (int i=n-2;i>=0;i--) { Ans1[i]+=Ans1[i+1]; if (Ans1[i+1]) Ans2[i]=max(Ans2[i],Ans2[i+1]); } for (int i=0;i<n;i++) printf("%lld %lld\n",Ans1[i],Ans1[i]?Ans2[i]:0); }
相关文章推荐
- 一个Angularjs实际项目的开发历程微博
- 【图像处理笔记】灰度变换
- AndroidSlidingUpPanel 使用控制和简单的分析方法
- 火狐重新打开标签页单独显示json的快 4000 捷操作方法
- 数据库范式简析和举例
- iOS系统介绍
- zoj2112
- 链表排序问题
- 【算法导论】快速排序
- Highmaps网页图表教程之绘图区显示标签显示数据标签定位
- Qt 中显示中文
- 直方图规定化
- C++指针加整数、两个指针相减的问题
- EXPLAIN sql优化方法2 Using temporary ; Using filesort
- 修改arm开发板的IP地址
- 快速排序原理
- zoj2112
- PHP查询数据库中满足条件的记录条数(二种实现方法)
- ORA-00904: "STUDENTNUMBER": 标识符无效
- javascript--QUnit【javascript单元测试框架】