BZOJ4199: [Noi2015]品酒大会
2016-06-26 20:01
330 查看
后缀数组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分组
View Code
也就是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分组
#include<bits/stdc++.h> using namespace std; #define N 300005 #define ll long long ll sum ,ans ; int n,val ,fa ,mx ,mn ,sz ; int m=256,c ,sa ,rk ,h ,t1 ,t2 ; char s ; struct Node{ int h,x,y; }g ; int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]); } void get_sa(int n){ int *x=t1,*y=t2; for(int i=0;i<m;i++)c[i]=0; for(int i=0;i<n;i++)c[x[i]=s[i]]++; for(int i=0;i<m;i++)c[i]+=c[i-1]; for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(int i=n-k;i<n;i++)y[p++]=i; for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k; for(int i=0;i<m;i++)c[i]=0; for(int i=0;i<n;i++)c[x[y[i]]]++; for(int i=0;i<m;i++)c[i]+=c[i-1]; for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y);x[sa[0]]=0;p=1; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++; if(p>=n)break; m=p; } } void get_height(int n){ for(int i=0;i<n;i++)rk[sa[i]]=i; int k=0; for(int i=0;i<n;i++){ if(k)k--; int j=sa[rk[i]-1]; while(s[i+k]==s[j+k])k++; h[rk[i]]=k; } } bool cmp(Node x,Node y){ return x.h>y.h; } void unite(int x,int y){ fa[x]=y; sz[y]+=sz[x]; mn[y]=min(mn[y],mn[x]); mx[y]=max(mx[y],mx[x]); } int main(){ scanf("%d",&n); scanf("%s",s); for(int i=1;i<=n;i++)scanf("%d",&val[i]); get_sa(n+1); get_height(n+1); for(int i=1;i<=n;i++)fa[i]=i,sz[i]=1,mx[rk[i-1]]=mn[rk[i-1]]=val[i]; for(int i=1;i<n;i++)g[i].h=h[i+1],g[i].x=i+1,g[i].y=i; sort(g+1,g+n,cmp); memset(sum,128,sizeof(sum)); for(int i=g[1].h,j=1;i>=0;i--){ ans[i]=ans[i+1],sum[i]=sum[i+1]; for(;j<n&&g[j].h==i;j++){ int x=find(g[j].x),y=find(g[j].y); sum[i]=max(sum[i],1ll*mx[x]*mx[y]); sum[i]=max(sum[i],1ll*mn[x]*mn[y]); ans[i]+=1ll*sz[x]*sz[y]; unite(x,y); } } for(int i=0;i<n;i++)printf("%lld %lld\n",ans[i],ans[i]==0?0:sum[i]); return 0; }
View Code
相关文章推荐
- 75. Sort Colors
- Android project的结构
- POJ 2231 Moo Volume , 简单公式推导
- 使用GeoGebra绘制简单函数图像
- 读《驯服烂代码——在编程操练中悟道》
- Leetcode-rotate-image
- Xcode常用快捷键
- POJ3080 Blue Jeans
- LVM 逻辑卷管理器
- Java Hashtable
- ECSHOP中ajax的调用原理
- 关于Oauth认证的那些事
- 第一个spring写的helloworld,好多细节
- [代码实例][gtk+]使用builder创建UI
- 两人之间的一些参数
- 通过vscode执行python程序
- JAVA自学之每日一题(一)
- C#串口通信编程
- WinForm窗体间传值的方法
- 高级语言采用左连接统计总和