码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ4199: [Noi2015]品酒大会

时间:2016-06-26 21:15:28      阅读:308      评论:0      收藏:0      [点我收藏+]

标签:

后缀数组height排序后并查集合并

也就是height较大的合并不影响较小的

num[i]=num[i+1]  ans[i]=ans[i+1]

合并时,num+=sz[x]*sz[y],ans=max(mn[x]*mn[y],mx[x]*mx[y],ans)

这种思路适应于求点对,还可以考虑启发式合并

后缀数组还有的常见思路就是二分,height分组

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 300005
 4 #define ll long long
 5 ll sum[N],ans[N];
 6 int n,val[N],fa[N],mx[N],mn[N],sz[N];
 7 int m=256,c[N],sa[N],rk[N],h[N],t1[N],t2[N];
 8 char s[N];
 9 struct Node{
10   int h,x,y;
11 }g[N];
12 int find(int x){
13   return fa[x]==x?x:fa[x]=find(fa[x]);
14 }
15 void get_sa(int n){
16   int *x=t1,*y=t2;
17   for(int i=0;i<m;i++)c[i]=0;
18   for(int i=0;i<n;i++)c[x[i]=s[i]]++;
19   for(int i=0;i<m;i++)c[i]+=c[i-1];
20   for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
21   for(int k=1;k<=n;k<<=1){
22     int p=0;
23     for(int i=n-k;i<n;i++)y[p++]=i;
24     for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
25     for(int i=0;i<m;i++)c[i]=0;
26     for(int i=0;i<n;i++)c[x[y[i]]]++;
27     for(int i=0;i<m;i++)c[i]+=c[i-1];
28     for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
29     swap(x,y);x[sa[0]]=0;p=1;
30     for(int i=1;i<n;i++)
31       x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
32     if(p>=n)break;
33     m=p;
34   }
35 }
36 void get_height(int n){
37   for(int i=0;i<n;i++)rk[sa[i]]=i;
38   int k=0;
39   for(int i=0;i<n;i++){
40     if(k)k--;
41     int j=sa[rk[i]-1];
42     while(s[i+k]==s[j+k])k++;
43     h[rk[i]]=k;
44   }
45 }
46 bool cmp(Node x,Node y){
47   return x.h>y.h;
48 }
49 void unite(int x,int y){
50   fa[x]=y;
51   sz[y]+=sz[x];
52   mn[y]=min(mn[y],mn[x]);
53   mx[y]=max(mx[y],mx[x]);
54 }
55 int main(){
56   scanf("%d",&n);
57   scanf("%s",s);
58   for(int i=1;i<=n;i++)scanf("%d",&val[i]);
59   get_sa(n+1);
60   get_height(n+1);
61   for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1,mx[rk[i-1]]=mn[rk[i-1]]=val[i];
62   for(int i=1;i<n;i++)g[i].h=h[i+1],g[i].x=i+1,g[i].y=i; 
63   sort(g+1,g+n,cmp);
64   memset(sum,128,sizeof(sum));
65   for(int i=g[1].h,j=1;i>=0;i--){
66     ans[i]=ans[i+1],sum[i]=sum[i+1];
67     for(;j<n&&g[j].h==i;j++){
68       int x=find(g[j].x),y=find(g[j].y);
69       sum[i]=max(sum[i],1ll*mx[x]*mx[y]);
70       sum[i]=max(sum[i],1ll*mn[x]*mn[y]);
71       ans[i]+=1ll*sz[x]*sz[y];
72       unite(x,y);
73     }
74   }
75   for(int i=0;i<n;i++)printf("%lld %lld\n",ans[i],ans[i]==0?0:sum[i]);
76   return 0;
77 }
View Code

 

BZOJ4199: [Noi2015]品酒大会

标签:

原文地址:http://www.cnblogs.com/wjyi/p/5618459.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!