NOI2015品酒大会 后缀数组
自己尝试敲后缀数组,发现难看(tiao)的不行,于是抄了板子
考虑建出hei以后转化出的问题:
对于一个数组中权值大于等于k的连续部分,求取两个数的方案数和两数积的最大值
(好气啊,可以有负数)
把询问倒序以后相当于连续部分之间会动态加元素,使他们连起来
维护一段极大连续段的最大值、最小值、长度,保存在左右两端——wtf我也不知道这算什么做法
然后瞎**乱搞一下,就能每次合并O(1)维护出来了(似乎没比并查集好多少)
1 #include <bits/stdc++.h> 2 #define N 300001 3 #define MIN -9223372036854775807 4 #define calc(x) (x)*((x)-1)/2 5 #define ll long long 6 using namespace std; 7 ll n,ans,ans2; 8 ll c[N],mi[N],ma[N],len[N],w[N]; 9 ll sa[N],Rank[N],height[N]; 10 ll wa[N],wb[N],wv[N],wd[N]; 11 ll out1[N],out2[N]; 12 struct node 13 { 14 ll x,y; 15 node(ll p,ll q) 16 { 17 x=p;y=q; 18 } 19 node() 20 { 21 } 22 } t[N]; 23 bool cmp(ll *r,ll a,ll b,ll l) 24 { 25 return r[a]==r[b]&&r[a+l]==r[b+l]; 26 } 27 bool com(node a,node b) 28 { 29 return a.x>b.x; 30 } 31 void da(ll *r,ll n,ll m) 32 { 33 ll *x=wa,*y=wb,*t; 34 for (ll i=0;i<m;i++) wd[i]=0; 35 for (ll i=0;i<n;i++) wd[x[i]=r[i]]++; 36 for (ll i=1;i<m;i++) wd[i]+=wd[i-1]; 37 for (ll i=n-1;i>=0;i--) sa[--wd[x[i]]]=i; 38 for (ll j=1,p=1,i;p<n;j<<=1,m=p) 39 { 40 for (p=0,i=n-j;i<n;i++) y[p++]=i; 41 for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j; 42 for (i=0;i<n;i++) wv[i]=x[y[i]]; 43 for (i=0;i<m;i++) wd[i]=0; 44 for (i=0;i<n;i++) wd[wv[i]]++; 45 for (i=1;i<m;i++) wd[i]+=wd[i-1]; 46 for (i=n-1;i>=0;i--) sa[--wd[wv[i]]]=y[i]; 47 for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) 48 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 49 } 50 } 51 void get_height(ll *r,ll n) 52 { 53 for (ll i=1;i<=n;i++) Rank[sa[i]]=i; 54 for (ll i=0,k=0,j;i<n;height[Rank[i++]]=k) 55 for (k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++); 56 } 57 void merge(ll x,ll y) 58 { 59 if(!len[x] || !len[y]) return; 60 ans2+=calc(len[x]+len[y]+1)-calc(len[x]+1)-calc(len[y]+1); 61 ans=max(ans,w[sa[x-len[x]]]*mi[y]);ans=max(ans,mi[x]*mi[y]); 62 ans=max(ans,w[sa[x-len[x]]]*ma[y]);ans=max(ans,ma[x]*ma[y]); 63 ll MI=min(mi[x],mi[y]),MA=max(ma[x],ma[y]); 64 mi[x-len[x]+1]=mi[y+len[y]-1]=MI; 65 ma[x-len[x]+1]=ma[y+len[y]-1]=MA; 66 len[x-len[x]+1]=len[y+len[y]-1]=len[x]+len[y]; 67 } 68 void add(ll now) 69 { 70 if(!now) return; 71 len[now]=1; 72 mi[now]=ma[now]=w[sa[now]]; 73 ans=max(ans,w[sa[now]]*w[sa[now-1]]); 74 ++ans2; 75 if(now) 76 merge(now-1,now); 77 if(now<n-1) 78 merge(now,now+1); 79 } 80 int main() 81 { 82 scanf("%lld",&n); 83 for(ll i=0;i<n;i++) 84 { 85 char ch; 86 while(ch=getchar(),!isalpha(ch)); 87 c[i]=ch-'a'+1; 88 } 89 for(ll i=0;i<n;i++) 90 scanf("%lld",&w[i]); 91 c[n]=0; 92 da(c,n+1,27); 93 get_height(c,n); 94 for(ll i=0;i<n;i++) 95 sa[i]=sa[i+1],height[i]=height[i+1]; 96 if(0) 97 for(ll i=0;i<n;i++) 98 { 99 printf("%lld %lld\n",sa[i],height[i]); 100 } 101 for(ll i=0;i<n;i++) 102 t[i]=node(height[i],i); 103 sort(t,t+n,com); 104 ll j=0; 105 ans=MIN;ans2=0; 106 for(ll i=0;i<n;i++) 107 len[i]=0,ma[i]=MIN,mi[i]=-MIN; 108 for(ll i=n-1;i>=0;i--) 109 { 110 while(j<n && t[j].x==i) add(t[j].y),j++; 111 out1[i]=ans2;out2[i]=(ans==MIN)?0:ans; 112 } 113 for(ll i=0;i<n;i++) 114 printf("%lld %lld\n",out1[i],out2[i]); 115 return 0; 116 }