【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)

题意:

 

两杯“r相似” (r>1)的酒同时也是“1 相似”、“2 相似”、…、“(r1) 相似”的。

n<=300000 abs(a[i])<=10^9

思路:对于i,j两个后缀,它们的贡献只与它们的lcp有关

而lcp又是它们之间height的最小值

所以可以把height从大到小排序

然后用并查集合并最值,方案数之类的

每次合并的都是排名相邻的一对后缀,相当于一段不相交的线段

每个集合中的lcp即为height的最小值

将r相似的加到r-1相似中

被UOJ的extra卡了一发,原来是0相似的初始最大值忘记初始化了

  1 const oo=1<<62;
  2 var sum,f:array[0..310000]of int64;
  3     sa,rank,height,id,mx,mn,size,a,fa,x,y,wc,wd,b:array[0..310000]of longint;
  4     n,m,i,p,q,t:longint;
  5     ch:ansistring;
  6 procedure swap(var x,y:longint);
  7 var t:longint;
  8 begin
  9  t:=x; x:=y; y:=t;
 10 end;
 11 
 12 function max(x,y:int64):int64;
 13 begin
 14  if x>y then exit(x);
 15  exit(y);
 16 end;
 17 
 18 function min(x,y:longint):longint;
 19 begin
 20  if x<y then exit(x);
 21  exit(y);
 22 end;
 23 
 24 procedure qsort(l,r:longint);
 25 var i,j,mid:longint;
 26 begin
 27  i:=l; j:=r; mid:=height[id[(l+r)>>1]];
 28  repeat
 29   while mid<height[id[i]] do inc(i);
 30   while mid>height[id[j]] do dec(j);
 31   if i<=j then
 32   begin
 33    swap(id[i],id[j]);
 34    inc(i); dec(j);
 35   end;
 36  until i>j;
 37  if l<j then qsort(l,j);
 38  if i<r then qsort(i,r);
 39 end;
 40 
 41 function find(k:longint):longint;
 42 begin
 43  if fa[k]<>k then fa[k]:=find(fa[k]);
 44  find:=fa[k];
 45 end;
 46 
 47 procedure merge(x,y:longint);
 48 begin
 49  size[y]:=size[y]+size[x];
 50  mx[y]:=max(mx[x],mx[y]);
 51  mn[y]:=min(mn[x],mn[y]);
 52  fa[x]:=y;
 53 end;
 54 
 55 function cmp(a,b,l:longint):boolean;
 56 begin
 57  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
 58 end;
 59 
 60 procedure getsa(n:longint);
 61 var i,j,p:longint;
 62 begin
 63  for i:=0 to n-1 do
 64  begin
 65   x[i]:=a[i];
 66   inc(wc[a[i]]);
 67  end;
 68  for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 69  for i:=n-1 downto 0 do
 70  begin
 71   dec(wc[x[i]]);
 72   sa[wc[x[i]]]:=i;
 73  end;
 74  j:=1; p:=1;
 75  while p<n do
 76  begin
 77   p:=0;
 78   for i:=n-j to n-1 do
 79   begin
 80    y[p]:=i; inc(p);
 81   end;
 82   for i:=0 to n-1 do
 83    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
 84   for i:=0 to n-1 do wd[i]:=x[y[i]];
 85   for i:=0 to m-1 do wc[i]:=0;
 86   for i:=0 to n-1 do inc(wc[wd[i]]);
 87   for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 88   for i:=n-1 downto 0 do
 89   begin
 90    dec(wc[wd[i]]);
 91    sa[wc[wd[i]]]:=y[i];
 92   end;
 93   for i:=0 to n do swap(x[i],y[i]);
 94   p:=1; x[sa[0]]:=0;
 95   for i:=1 to n-1 do
 96    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
 97     else
 98     begin
 99      x[sa[i]]:=p; inc(p);
100     end;
101   j:=j*2;
102   m:=p;
103  end;
104 end;
105 
106 procedure getheight(n:longint);
107 var i,j,k:longint;
108 begin
109  for i:=1 to n do rank[sa[i]]:=i;
110  k:=0;
111  for i:=0 to n-1 do
112  begin
113   if k>0 then dec(k);
114   j:=sa[rank[i]-1];
115   while a[i+k]=a[j+k] do inc(k);
116   height[rank[i]]:=k;
117  end;
118 end;
119 
120 begin
121  assign(input,'bzoj4199.in'); reset(input);
122  assign(output,'bzoj4199.out'); rewrite(output);
123  readln(n);
124  readln(ch);
125  for i:=0 to n-1 do a[i]:=ord(ch[i+1])-ord('a')+1;
126  a[n]:=0; m:=300;
127  getsa(n+1);
128  getheight(n);
129  for i:=0 to n-1 do read(b[i]);
130  for i:=1 to n do
131  begin
132   fa[i]:=i;
133   size[i]:=1; mx[i]:=b[sa[i]]; mn[i]:=mx[i];
134   f[i]:=-oo;
135  end;
136  f[0]:=-oo;
137  for i:=1 to n-1 do id[i]:=i+1;
138  qsort(1,n-1);
139  for i:=1 to n-1 do
140  begin
141   p:=find(id[i]-1); q:=find(id[i]);
142   t:=height[id[i]];
143   sum[t]:=sum[t]+int64(size[p])*size[q];
144   f[t]:=max(f[t],int64(mx[p])*mx[q]);
145   f[t]:=max(f[t],int64(mx[p])*mn[q]);
146   f[t]:=max(f[t],int64(mn[p])*mx[q]);
147   f[t]:=max(f[t],int64(mn[p])*mn[q]);
148   merge(p,q);
149  end;
150  for i:=n-2 downto 0 do
151  begin
152   sum[i]:=sum[i]+sum[i+1];
153   f[i]:=max(f[i],f[i+1]);
154  end;
155  for i:=0 to n-1 do
156   if f[i]>-oo then writeln(sum[i],' ',f[i])
157    else writeln(0,' ',0);
158 
159  close(input);
160  close(output);
161 end.

 

posted on 2017-04-14 11:40  myx12345  阅读(152)  评论(0编辑  收藏  举报

导航