【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)
题意:
两杯“r相似” (r>1)的酒同时也是“1 相似”、“2 相似”、……、“(r−1) 相似”的。
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.
null