1. 程式人生 > >2017CCPC-哈爾濱站 Hdu-6230 Palindrome Manacher 主席樹

2017CCPC-哈爾濱站 Hdu-6230 Palindrome Manacher 主席樹

manacher else 裸題 b- fin ret acm clas --

題面

題意:給你一個字符串,問你滿足s[i]=s[2n-i]=s[2n+i-2]的子串(這子串長度為3n-2)有多少個,原字符串長度<=5e5

題解:對於這種子串,其實要滿足2個回文,跑過一次Manacher後,len[i]表示以i向兩邊擴展最遠的回文串長度,

那麽對於答案,實際就是統計滿足下列條件(i,j)的對數

i <= j

j - i <= len[i]

j - i <= len[j]

移項就是

i >= j - len[j]

j <= i + len[i]

那麽相當於,枚舉i,詢問(i,i+len[i])區間內,有多少個數(這裏指權值 j - len[j])小於等於i

就是問區間內小於某個數的個數,那就是主席樹裸題(好像其他人都寫的樹狀樹狀ORZ)

 1 #include<bits/stdc++.h>
 2 #define N 500505
 3 using namespace std;
 4 int sum[N*25],rt[N*25],lc[N*25],rc[N*25];
 5 int a[N],b[N],len[N],p,node_cnt,cnt,value[N];
 6
char s[N]; 7 void build(int &t,int l, int r) 8 { 9 t=++node_cnt; 10 sum[t]=0; 11 if (l==r) return; 12 int mid=(l+r)>>1; 13 build(lc[t],l,mid); 14 build(rc[t],mid+1,r); 15 } 16 int modify(int o,int l,int r) 17 { 18 int oo = ++node_cnt; 19 lc[oo]=lc[o]; rc[oo]=rc[o]; sum[oo]=sum[o]+1
; 20 if (l==r) return oo; 21 int mid=(l+r)>>1; 22 if (p<=mid) lc[oo]=modify(lc[oo],l,mid); 23 else rc[oo]=modify(rc[oo],mid+1,r); 24 return oo; 25 } 26 int query(int u,int v,int l,int r,int k) 27 { 28 int ans,mid=((l+r)>>1); 29 if (r<=k) return sum[v]-sum[u]; 30 if (l>k) return 0; 31 ans=query(lc[u],lc[v],l,mid,k); 32 if (mid<k) ans=ans+query(rc[u],rc[v],mid+1,r,k); 33 return ans; 34 } 35 void manacher() 36 { 37 int pos=0,R=0; 38 for (int i=1;i<=cnt;i++) 39 { 40 if (i<R) len[i]=min(len[2*pos-i],R-i); else len[i]=1; 41 while (1<=i-len[i]&&i+len[i]<=cnt&&s[i-len[i]]==s[i+len[i]]) len[i]++; 42 if (i+len[i]>R) {pos=i;R=i+len[i];} 43 } 44 for(int i=1;i<=cnt;i++) 45 { 46 a[i]=i-len[i]+1; 47 b[i]=a[i]; 48 } 49 } 50 int main() 51 { 52 int k, n, q, nn, v, l, r, x,T; 53 scanf("%d\n",&T); 54 while (T--) 55 { 56 scanf("%s",s+1); 57 cnt=strlen(s+1); 58 manacher(); 59 sort(b+1,b+1+cnt); 60 nn=unique(b+1,b+cnt+1)-b-1; 61 node_cnt=0; 62 build(rt[0],1,nn); 63 for (int i=1;i<=cnt;i++) 64 { 65 p=lower_bound(b+1,b+nn+1,a[i])-b; 66 rt[i]=modify(rt[i-1],1,nn); 67 } 68 long long ans=0; 69 for (int i=1;i<=cnt;i++) 70 { 71 x=lower_bound(b+1,b+nn+1,i)-b; 72 if (x==nn+1) x--; 73 if (b[x]>i) x--; 74 if(x==0) continue; 75 if(min(len[i]+i-1,cnt)<i+1) continue; 76 ans=ans+query(rt[i],rt[min(len[i]+i-1,cnt)],1,nn,x); 77 } 78 printf("%lld\n",ans); 79 } 80 }

2017CCPC-哈爾濱站 Hdu-6230 Palindrome Manacher 主席樹