您的位置:首页 > 其它

bzoj4199&uoj131: [Noi2015]品酒大会

2015-08-16 16:23 302 查看
传送门:http://uoj.ac/problem/131

思路:先求出height,然后根据排名重新给后缀标号,按height从大到小做,每次合并i和i-1,用并查集维护,更新答案。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
const int maxn=300010;
using namespace std;
typedef long long ll;
int n,a[maxn];ll ans[maxn],cnt[maxn];char s[maxn];
struct orz{int h,pos;}cls[maxn];
bool cmp(orz a,orz b){return a.h>b.h;}

struct Tufs{
int maxs[maxn],mins[maxn],fa[maxn],siz[maxn];
int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
void merge(int x,int y){
x=getfa(x),y=getfa(y),fa[y]=x;
maxs[x]=max(maxs[x],maxs[y]);
mins[x]=min(mins[x],mins[y]);
siz[x]+=siz[y];
}
}ufs;

struct Suffix_Array{
int sa[maxn],rank[maxn],t1[maxn],t2[maxn],sum[maxn],h[maxn];
void getsa(){
int *x=t1,*y=t2,m=255,p=0;
for (int i=1;i<=n;i++) sum[x[i]=s[i]]++;
for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
for (int i=n;i;i--) sa[sum[x[i]]--]=i;
for (int j=1;p<n;j<<=1,m=p){
p=0;
for (int i=n-j+1;i<=n;i++) y[++p]=i;
for (int i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) sum[x[y[i]]]++;
for (int i=1;i<=m;i++) sum[i]+=sum[i-1];
for (int i=n;i;i--) sa[sum[x[y[i]]]--]=y[i];
swap(x,y),x[sa[1]]=p=1;
for (int i=2;i<=n;i++){
if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j]) p++;
x[sa[i]]=p;
}
}

memcpy(rank,x,sizeof(rank));
}
void geth(){
for (int i=1,j=0;i<=n;i++){
if (rank[i]==1) continue;
while (s[i+j]==s[sa[rank[i]-1]+j]) j++;
h[rank[i]]=j;
if (j) j--;
}
}
void work(){
memset(ans,128,sizeof(ans));
for (int i=2;i<=n;i++) cls[i-1]=(orz){h[i],i};
sort(cls+1,cls+n,cmp);
for (int i=cls[1].h,j=1;i>=0;i--){
ans[i]=ans[i+1],cnt[i]=cnt[i+1];
for (;j<n&&cls[j].h==i;j++){
int x=ufs.getfa(cls[j].pos),y=ufs.getfa(cls[j].pos-1);
ans[i]=max(ans[i],1ll*ufs.maxs[x]*ufs.maxs[y]);
ans[i]=max(ans[i],1ll*ufs.mins[x]*ufs.mins[y]);
cnt[i]+=1ll*ufs.siz[x]*ufs.siz[y];
ufs.merge(x,y);
}
}
for (int i=0;i<n;i++)
if (cnt[i]) printf("%lld %lld\n",cnt[i],ans[i]);
else puts("0 0");
}
}SA;

int main(){
scanf("%d%s",&n,s+1);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
SA.getsa(),SA.geth();
for (int i=1;i<=n;i++) ufs.fa[i]=i,ufs.mins[SA.rank[i]]=ufs.maxs[SA.rank[i]]=a[i],ufs.siz[i]=1;
SA.work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: