NOI 2015 品酒大会
题意:戳这里
题解:这个一看就知道是后缀数组。。。。。我们得到hei数组之后从大到小排序,一个个加进去并统计答案,用并查集维护连续的一段,注意连续的一段要保留最小值(因为有负数)
代码:
#include <bits/stdc++.h>
#define For(ii,a,b) for (int ii=(a);ii<=(b);ii++)
#define Rof(ii,a,b) for (int ii=(a);ii>=(b);ii--)
#define rep(ii,a,b) for (int ii=(a);ii<=(b);ii++)
#define rek(ii,a,b) for (int ii=(a);ii>=(b);ii--)
#define Mem(a,t) memset(a,t,sizeof(a))
using namespace std;
const int maxL=300005;
const long long INF=(long long)1000000000*1000000000+4;
int N;
int rankk[maxL*2+1],sa[maxL],hei[maxL],s[maxL];
int w[maxL],m[maxL];
char ss[maxL];
///-----
int a[maxL],fa[maxL],minx[maxL],maxx[maxL],ll[maxL],rr[maxL];
bool bb[maxL];
struct point{
int x,y;
friend bool operator <(const point&a,const point&b ){
return a.x>b.x;
}
}pp[maxL];
bool campar(point a,point b){
return a.x>b.x;
}
long long ans[maxL],sum[maxL];
///-----
void init(){
scanf("%d",&N);
scanf("%s",ss);
rep(i,1,N) s[i]=ss[i-1];
rep(i,1,N) scanf("%d",&a[i]);
}
void get_sa_hei(int *s,int N)
{
Mem(rankk,0);
For(i,0,maxL-1) w[i]=0;
For(i,1,N) w[s[i]]++;
For(i,1,maxL-1) w[i]+=w[i-1];
Rof(i,N,1) m[w[s[i]]--]=i;
rankk[m[1]]=1;
For(i,2,N)
if (s[m[i]]==s[m[i-1]]) rankk[m[i]]=rankk[m[i-1]];
else rankk[m[i]]=rankk[m[i-1]]+1;
for (int k=1; k<=N; k<<=1)
{
Mem(w,0);
For(i,1,N) w[rankk[i+k]]++;
For(i,1,N) w[i]+=w[i-1];
Rof(i,N,1) m[w[rankk[i+k]]--]=i;
Mem(w,0);
For(i,1,N) w[rankk[i]]++;
For(i,1,N) w[i]+=w[i-1];
Rof(i,N,1) sa[w[rankk[m[i]]]--]=m[i];
m[sa[1]]=1;
For(i,2,N)
if (rankk[sa[i]]==rankk[sa[i-1]] && rankk[sa[i]+k]==rankk[sa[i-1]+k])
m[sa[i]]=m[sa[i-1]];
else m[sa[i]]=m[sa[i-1]]+1;
For(i,1,N) rankk[i]=m[i];
}
For(i,1,N) sa[rankk[i]]=i;
for (int i=1,j=0; i<=N; i++)
{
if (rankk[i]==1) continue;
for (j?j--:0; i+j<=N && sa[rankk[i]-1]+j<=N && s[sa[rankk[i]-1]+j]==s[i+j]; j++);
hei[rankk[i]]=j;
}
}
int getfa(int x){
if (fa[x]==x) return x;
fa[x]=getfa(fa[x]);
return fa[x];
}
void solve(){
rep(i,1,N) fa[i]=i,ll[i]=i,rr[i]=i;
rep(i,1,N){
pp[i].x=hei[i];
pp[i].y=i;
}
sort(pp+1,pp+N+1);
rep(i,0,N-1) ans[i]=-INF;
rep(i,0,N-1) bb[i]=false;
Mem(sum,0);
rep(i,1,N) minx[i]=a[sa[i]],maxx[i]=a[sa[i]];
rep(i,1,N){
if (pp[i].y!=1)
{
// printf("%d %d ",pp[i].x,pp[i].y);
int t1=getfa(pp[i].y-1);
int t2=getfa(pp[i].y);
if ((long long)minx[t1]*minx[t2]>ans[pp[i].x]) {
ans[pp[i].x]=(long long)minx[t1]*minx[t2];
}
if ((long long)maxx[t1]*maxx[t2]>ans[pp[i].x]) {
ans[pp[i].x]=(long long)maxx[t1]*maxx[t2];
}
bb[pp[i].x]=true;
sum[pp[i].x]+=(long long)(rr[t1]-ll[t1]+1)*(rr[t2]-ll[t2]+1);
fa[t1]=t2;
ll[t2]=ll[t1];
minx[t2]=min(minx[t2],minx[t1]);
maxx[t2]=max(maxx[t2],maxx[t1]);
}
}
rek(i,N-1,0) sum[i]+=sum[i+1];
rek(i,N-1,0)
{
if (bb[i+1]) ans[i]=max(ans[i+1],ans[i]),bb[i]=true;
}
rep(i,0,N-1){
if (bb[i]) printf("%lld %lld\n",sum[i],ans[i]);else printf("0 0\n");
}
}
int main(){
init();
get_sa_hei(s,N);
solve();
}