码迷,mamicode.com
首页 > 其他好文 > 详细

2017CCPC-哈尔滨站 Hdu-6230 Palindrome Manacher 主席树

时间:2018-10-07 00:43:03      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:name   show   条件   --   pre   else   fine   node   void   

题面

题意:给你一个字符串,问你满足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 主席树

标签:name   show   条件   --   pre   else   fine   node   void   

原文地址:https://www.cnblogs.com/qywhy/p/9749063.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!