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

bzoj4199

时间:2016-07-10 21:54:51      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

看到这题我就伤心,当初想到了正解却因为各种sb原因没有写……

好吧,其实我的正解是比较挫的……

大家似乎都用了后缀数组,我用了后缀自动机(后缀树)

其实SAM是很好想得,用SAM建出后缀树后

我们考虑树上每个节点对答案的贡献,0相似就不必说了

考虑到任意两个后缀的LCP即这两个后缀所在节点的LCA的节点所能接受的最长子串mx[i]

又每个节点能接收的子串长度为[mx[fa[i]]+1,mx[i]]

我们很容易想出问题1:设节点i的子树内代表后缀的节点个数为s,那么节点i对区间[mx[fa[i]]+1,mx[i]]贡献是s*(s-1)/2

问题2:很显然找出节点i子树内max{最大*次大,最小*次小}(因为有负数),这要dfs序+线段树维护,然后区间覆盖再来个线段树……

总复杂度是O(nlogn),实际是能过的(但是跑得似乎比SA做法慢……)

技术分享
  1 #include<iostream>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<stdlib.h>
  6 #define ll long long
  7 #define N 300005
  8 using namespace std;
  9 const ll inf=-1000000001;
 10 const ll small=-1000000002000000001ll;
 11 int go[2*N][26],fa[2*N],w[2*N],mx[2*N],p[2*N],a[2*N],b[2*N],l[2*N],r[2*N];
 12 struct node{ll b1,b2,s1,s2;} tree[8*N];
 13 struct way{int po,next;} e[2*N];
 14 ll ans[4*N][2];
 15 int n,last,t,len;
 16 char s[N];
 17 
 18 void ins(int x,int y)
 19 {
 20      e[++len].po=y;
 21      e[len].next=p[x];
 22      p[x]=len;
 23 }
 24      
 25 void add(int c,int x)
 26 {
 27      int np,nq,q,p=last;
 28      np=++t; mx[np]=mx[p]+1; a[np]=x; w[np]=1;
 29      for (;p&&!go[p][c];p=fa[p]) go[p][c]=np;
 30      if (!p) fa[np]=1;
 31      else {
 32           q=go[p][c];
 33           if (mx[q]==mx[p]+1) fa[np]=q;
 34           else {
 35                nq=++t; a[t]=inf;
 36                mx[nq]=mx[p]+1;
 37                memcpy(go[nq],go[q],sizeof(go[q]));
 38                fa[nq]=fa[q]; fa[np]=fa[q]=nq;
 39                for (;go[p][c]==q;p=fa[p]) go[p][c]=nq;
 40           }
 41      }
 42      last=go[last][c];
 43 }
 44 
 45 void dfs(int x)
 46 {
 47      l[x]=++t; b[t]=x; 
 48      for (int i=p[x];i;i=e[i].next)
 49      {
 50          int y=e[i].po;
 51          dfs(y); w[x]+=w[y];
 52      }
 53      r[x]=t;
 54 }
 55  
 56 void update(node &a,node x,node y)
 57 {
 58      if (x.b1>y.b1) 
 59      {
 60         a.b1=x.b1;
 61         a.b2=max(x.b2,y.b1);
 62      }         
 63      else {
 64           a.b1=y.b1;
 65           a.b2=max(x.b1,y.b2);
 66      } 
 67      if (x.s1>y.s1)
 68      {
 69         a.s1=y.s1;
 70         a.s2=min(x.s1,y.s2);
 71      }
 72      else {
 73           a.s1=x.s1;
 74           a.s2=min(x.s2,y.s1);
 75      }   
 76 }
 77 void build(int i,int l, int r)
 78 {
 79      if (l==r)
 80      {
 81         tree[i].b1=a[b[l]];
 82         tree[i].b2=inf; 
 83         tree[i].s2=-inf;
 84         tree[i].s1=(a[b[l]]==inf)?-inf:a[b[l]];
 85         return;
 86      }         
 87      int m=(l+r)>>1;
 88      build(i*2,l,m);
 89      build(i*2+1,m+1,r);
 90      update(tree[i],tree[i*2],tree[i*2+1]);
 91 }
 92 
 93 node get(int i,int l,int r,int x, int y)
 94 {
 95      if (x<=l&&y>=r) return tree[i];
 96      int m=(l+r)>>1;
 97      node s,b,c; 
 98      b.b1=b.b2=c.b1=c.b2=inf; 
 99      b.s1=b.s2=c.s1=c.s2=-inf;
100      if (x<=m) b=get(i*2,l,m,x,y);
101      if (y>m) c=get(i*2+1,m+1,r,x,y);
102      update(s,b,c);
103      return s;
104 }
105 
106 void work(int i,int l,int r,int x,int y,ll a,ll b)
107 {
108      if (x<=l&&y>=r) {ans[i][0]+=a; ans[i][1]=max(ans[i][1],b);}
109      else {
110           int m=(l+r)>>1;
111           if (ans[i][0]) 
112           {
113              ans[i*2][0]+=ans[i][0]; ans[i*2+1][0]+=ans[i][0];
114              ans[i][0]=0;
115           }
116           if (ans[i][1]>small) 
117           {
118              ans[i*2][1]=max(ans[i][1],ans[i*2][1]); ans[i*2+1][1]=max(ans[i][1],ans[i*2+1][1]);
119              ans[i][1]=small;
120           }
121           if (x<=m) work(i*2,l,m,x,y,a,b);
122           if (y>m) work(i*2+1,m+1,r,x,y,a,b);
123      }
124 }  
125 
126 void getans(int i,int l,int r)
127 {
128      if (l==r) 
129      {
130          if (ans[i][0]==0) ans[i][1]=0;
131          printf("%lld %lld\n",ans[i][0],ans[i][1]);
132      }
133      else {
134           int m=(l+r)>>1;
135           if (ans[i][1]>small) {ans[i*2][1]=max(ans[i][1],ans[i*2][1]); ans[i*2+1][1]=max(ans[i][1],ans[i*2+1][1]);}
136           if (ans[i][0]) {ans[i*2][0]+=ans[i][0]; ans[i*2+1][0]+=ans[i][0];}
137           getans(i*2,l,m);
138           getans(i*2+1,m+1,r);
139      }
140 }
141      
142 int main()
143 {   
144     scanf("%d",&n); scanf("%s",s+1);
145     for (int i=1; i<=n; i++) scanf("%d",&b[i]);
146     if (n==1) {puts("0 0");return 0;}
147     t=last=1; a[1]=inf;
148     for (int i=n;i;i--) add(s[i]-a,b[i]);
149     for (int i=2;i<=t; i++) ins(fa[i],i);
150     t=0; dfs(1);
151     build(1,1,t);   
152     for (int i=1; i<=n*4;i++) ans[i][1]=small;    
153     for (int i=2; i<=t; i++) 
154     {   
155         if (w[i]<=1) continue;
156         node c=get(1,1,t,l[i],r[i]);
157         ll x=max(c.b1*c.b2,c.s1*c.s2);
158         work(1,1,n-1,mx[fa[i]]+1,mx[i],(ll)(w[i]-1)*(ll)(w[i])/2,x);
159     }
160     printf("%lld %lld\n",(ll)(w[1]-1)*(ll)(w[1])/2,max(tree[1].b1*tree[1].b2,tree[1].s1*tree[1].s2));
161     getans(1,1,n-1);
162     return 0;
163 }
164     
View Code

 

bzoj4199

标签:

原文地址:http://www.cnblogs.com/phile/p/5658558.html

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