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 }

 

posted @ 2017-04-19 11:05  ws_ccd  阅读(137)  评论(0编辑  收藏  举报