給定序列\(a\)和\(b\),求全部區間\(min\{a_l,a_{l+1}...a_r\}*sum\{b_l,b_{l+1}...b_r\}\)。node
預處理出每一個\(a_i\)做爲最小值延伸的區間,而後線段樹維護\(b\)序列,對於每一個\(a_i\),根據正負,求出包含\(b_i\)的最大子段和和最小子段和。c++
#include <bits/stdc++.h> using namespace std; #define ls i<<1 #define rs i<<1|1 #define mid (l+r)/2 typedef long long ll; const int N=3e6+15; int n,a[N],b[N],le[N],ri[N],q[N]; struct node{ ll sum,lmx,rmx; }tr[N*4]; void pushup(int i){ tr[i].sum=tr[ls].sum+tr[rs].sum; tr[i].lmx=max(tr[ls].lmx,tr[ls].sum+tr[rs].lmx); tr[i].rmx=max(tr[rs].rmx,tr[rs].sum+tr[ls].rmx); } void build(int i,int l,int r){ if(l==r){ tr[i].sum=tr[i].lmx=tr[i].rmx=b[l]; return; } build(ls,l,mid); build(rs,mid+1,r); pushup(i); } node query(int i,int l,int r,int ql,int qr){ if(ql<=l && qr>=r){ return tr[i]; } if(qr<=mid){ return query(ls,l,mid,ql,qr); } if(ql>mid){ return query(rs,mid+1,r,ql,qr); } node ll=query(ls,l,mid,ql,qr); node rr=query(rs,mid+1,r,ql,qr); node ans{}; ans.sum=ll.sum+rr.sum; ans.lmx=max(ll.lmx,ll.sum+rr.lmx); ans.rmx=max(rr.rmx,rr.sum+ll.rmx); return ans; } int main(void){ // freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); } int l=1; int l1=1,r1=0; for(int r=1;r<=n;r++){ while(l1<=r1 && a[r]<a[q[r1]]){ ri[q[r1]]=r-1; r1--; } q[++r1]=r; l++; } while(l1<=r1){ ri[q[r1]]=n; r1--; } l=1; l1=1,r1=0; for(int r=n;r>=1;r--){ while(l1<=r1 && a[r]<a[q[r1]]){ le[q[r1]]=r+1; r1--; } q[++r1]=r; l++; } while(l1<=r1){ le[q[r1]]=1; r1--; } ll ans=0; build(1,1,n); for(int i=1;i<=n;i++){ if(a[i]<0){ continue; } node lt=query(1,1,n,le[i],i); node rt=query(1,1,n,i,ri[i]); ll t=max(max(lt.rmx,rt.lmx),max(1ll*b[i],lt.rmx+rt.lmx-b[i])); ans=max(ans,t*a[i]); } for(int i=1;i<=n;i++){ b[i]=-b[i]; } build(1,1,n); for(int i=1;i<=n;i++){ if(a[i]>0){ continue; } node lt=query(1,1,n,le[i],i); node rt=query(1,1,n,i,ri[i]); ll t=max(max(lt.rmx,rt.lmx),max(1ll*b[i],lt.rmx+rt.lmx-b[i])); ans=max(ans,-t*a[i]); } printf("%lld\n",ans); return 0; }
給一個字符串,一個子串與其逆序子串算同一個,求子串個數。數組
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+50; char str[N]; int s[N],sa[N],rk[N],h[N]; int t[N],t2[N],c[N]; void Sa(int n,int m=128){ n++; int *x=t,*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=1;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=1;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); p=1; x[sa[0]]=0; for(int i=1;i<n;i++){ x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; } if(p>=n){ break; } m=p; } 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; } } ll getP(int n){ ll ans=0; int mid=n/2; for(int i=1;i<=n;i++){ if(sa[i]>mid){ ans+=1ll*(n-sa[i]-h[i]); }else if(sa[i]==mid){ continue; }else{ ans+=max(0ll,1ll*(mid-sa[i]-h[i])); } } return ans; } struct PT{ int next[N][26],fail[N],cnt[N],num[N],len[N]; int S[N],last,id[N],n,p; int newnode(int l){ for(int i=0;i<26;i++){ next[p][i]=0; } cnt[p]=0; num[p]=0; len[p]=l; return p++; } void init(){ p=0; newnode(0); newnode(-1); last=0; n=0; S[n]=-1; fail[0]=1; } int getFail(int x){ while(S[n-len[x]-1]!=S[n]){ x=fail[x]; } return x; } void add(int c){ c-='a'; S[++n]=c; int cur=getFail(last); if(!next[cur][c]){ int now=newnode(len[cur]+2); fail[now]=next[getFail(fail[cur])][c]; num[now]=num[cur]+1; next[cur][c]=now; } last=next[cur][c]; cnt[last]++; id[last]=n; } void count(){ for(int i=p-1;i>=0;i--){ cnt[fail[i]]+=cnt[i]; } } }ac; int main(void){ // freopen("in.txt","r",stdin); scanf("%s",str); int n=strlen(str); for(int i=0;i<n;i++){ s[i]=str[i]-'a'+2; } s[n]=1; for(int i=0;i<n;i++){ s[n+1+i]=str[n-1-i]-'a'+2; } Sa(n*2+1); ll p=getP(n*2+1); ac.init(); for(int i=0;i<n;i++){ ac.add(str[i]); } ll q=ac.p-2; ll ans=(p+q)/2; printf("%lld\n",ans); return 0; }