bzoj 3790: 神奇项链
IQ--
其实就是用manacher搞出来一些回文的线段,然后就是判断如何用最少的线段覆盖整个区间就行了,
区间覆盖的话,DP一下,用BIT优化一下。
1 #include <bits/stdc++.h> 2 #define inf 1e9 3 using namespace std; 4 5 const int maxn=100005; 6 7 int n,m,cnt; 8 int p[maxn<<1],c[maxn]; 9 char ch[maxn],a[maxn<<1]; 10 struct seg{ 11 int l,r; 12 }l[maxn]; 13 14 int lowbit(int x) {return x&(-x);} 15 int query(int x) 16 { 17 if (!x) return 0; 18 int tmp=inf; 19 for (; x<=n; x+=lowbit(x)) tmp=min(c[x],tmp); 20 return tmp; 21 } 22 void change(int x, int val) 23 { 24 for (;x;x-=lowbit(x)) c[x]=min(c[x],val); 25 } 26 27 bool operator < (seg a, seg b) 28 { 29 return a.r<b.r; 30 } 31 void add(int x, int y) 32 { 33 x=x/2+1; y=y/2-1; 34 if (x>y) return; 35 l[++cnt]=(seg){x,y}; 36 } 37 void manachar() 38 { 39 m=2*n+1; 40 for (int i=1; i<=n; i++) a[i<<1]=ch[i],a[i<<1|1]='#'; 41 a[0]='+'; a[m+1]='-'; a[1]='#'; 42 int mx=0,id=0; 43 for (int i=1; i<=m; i++) 44 { 45 if (mx>i) p[i]=min(mx-i,p[2*id-i]); else p[i]=1; 46 while (a[i+p[i]]==a[i-p[i]]) p[i]++; 47 add(i-p[i],i+p[i]); 48 if (p[i]+i>mx) mx=p[i]+i,id=i; 49 } 50 } 51 52 int main() 53 { 54 while (scanf("%s",ch+1)!=EOF) 55 { 56 cnt=0; 57 n=strlen(ch+1); for (int i=1; i<=n; i++) c[i]=inf; 58 manachar(); sort(l+1,l+cnt+1); 59 int ans=inf; 60 // for (int i=1; i<=cnt; i++) printf("%d %d\n",l[i].l,l[i].r); 61 for (int i=1; i<=cnt; i++) 62 { 63 int x=query(l[i].l-1)+1; 64 change(l[i].r,x); 65 if (l[i].r==n) ans=min(ans,x); 66 } 67 cout<<ans-1<<endl; 68 } 69 return 0; 70 }